Sql Querying, групповые отношения - PullRequest
3 голосов
/ 10 мая 2010

Предположим, у меня есть две таблицы:

Group
(
    id integer primary key,
    someData1 text,
    someData2 text
)

GroupMember
(
    id integer primary key,
    group_id   foreign key to Group.id,
    someData   text
)

Я знаю, что мой синтаксис SQL неправильный :) Надеюсь, он достаточно понятен. Моя проблема заключается в следующем: я хочу загрузить запись группы и все записи GroupMember, связанные с этой группой. На мой взгляд, есть два варианта.

Один запрос:

SELECT Group.id, Group.someData1, Group.someData2 GroupMember.id, GroupMember.someData
FROM Group INNER JOIN GroupMember ...
WHERE Group.id = 4;

Два запроса:

SELECT id, someData2, someData2
FROM Group
WHERE id = 4;

SELECT id, someData
FROM GroupMember
WHERE group_id = 4;

Преимущество первого решения состоит в том, что он состоит только из одного обхода базы данных, но имеет недостаток, заключающийся в возврате избыточных данных (все данные группы дублируются для каждого члена группы)

Второе решение не возвращает повторяющихся данных, но включает в себя две поездки в базу данных.

Что здесь предпочтительнее? Я предполагаю, что есть некоторый порог, такой, что если размеры групп станут достаточно большими, стоимость возврата всех избыточных данных будет больше, чем издержки, связанные с дополнительным вызовом базы данных. О каких еще вещах я должен думать здесь?

Спасибо, Иордания

Ответы [ 7 ]

3 голосов
/ 10 мая 2010

Если вы действительно хотите, чтобы результаты были объединены, я считаю, что объединение на уровне сервера всегда эффективнее. Процессор SQL предназначен для сопоставления наборов данных. Если вы действительно хотите получить результаты 2 операторов SQL, вы всегда можете отправить два оператора в одном пакете, разделенных точкой с запятой, и получить два набора результатов обратно с одним циклом в базу данных.

2 голосов
/ 10 мая 2010

Как окончательно используются данные, является важным и неизвестным фактором.

Я предлагаю метод единого запроса для большинства приложений. Правильная индексация сделает запрос более эффективным, чем метод двух запросов.

Преимущество метода одиночного запроса также заключается в том, что он остается действительным, если вам нужно выбрать более одной группы.

1 голос
/ 10 мая 2010

Если вы когда-либо будете получать только одну групповую запись с каждым запросом к базе данных, тогда я выберу второй вариант. Если вы извлекаете несколько записей групп и связанных записей членов группы, используйте объединение, так как это будет намного быстрее.

0 голосов
/ 10 мая 2010

Это действительно очень зависит от того, как вы будете использовать данные.

Для страховки, если вы собирали список членов группы для почтовой рассылки, и вам нужно имя группы для каждого письма, которое вы собираетесь отправить участнику, и вы не используете уровень группы, тогда одиночный объединенный запрос имеет большой смысл.

Но если, скажем, вы кодируете экран или отчет с основными данными со страницей для каждой группы и отображаете информацию как на уровне группы, так и на уровне участников, то два отдельных запроса, вероятно, наиболее полезны.

Если вы не извлекаете достаточно большие объемы данных (десятки тысяч групп с сотнями членов на группу или аналогичные порядки величин), маловероятно, что вы увидите большую разницу между характеристиками двух подходов.

0 голосов
/ 10 мая 2010

В зависимости от типа базы данных и вашего веб-приложения вы можете вернуть результаты двух операторов SQL за одну поездку (например, хранимая процедура в SQL Server 2005).

Если вы создаете отчет, который требует много полей из таблицы групп, возможно, вы не захотите увеличивать объем данных в первом запросе.

Если это приложение ввода данных какого-либо типа, вы, вероятно, уже представили данные группы пользователю, чтобы они могли заполнить идентификатор группы в предложении where (или, предпочтительно, через какой-либо параметр), и теперь им нужен Результаты участника.

0 голосов
/ 10 мая 2010

В общем, это зависит от того, какой тип данных вы пытаетесь отобразить.

Если вы показываете одну группу и всех ее участников, различия в производительности между этими двумя вариантами будут незначительными.

Если вы показываете много групп и всех их участников, накладные расходы, связанные с обходом базы данных для каждой последующей группы, быстро перевесят любую выгоду, полученную вами от получения немного меньшего количества данных.

Некоторые другие вещи, которые вы могли бы рассмотреть в своих рассуждениях

  • Размер результирующего набора - для многих групп и членов размер вашего результирующего набора может стать ограничивающим фактором, так как размер для извлечения и сохранения его в памяти увеличивается. Это может произойти со вторым вариантом. Возможно, вы захотите рассмотреть подкачку данных, чтобы одновременно получать только определенное подмножество.

  • Ленивая загрузка - Если вы получаете только членов некоторых групп или пользователь запрашивает участников по одной группе за раз, рассмотрите вариант Ленивая загрузка. Это означает только выполнение дополнительного запроса, чтобы получить членов группы при необходимости. Это имеет смысл только в определенных случаях использования, но может быть гораздо более эффективным, чем предварительное получение всех данных.

0 голосов
/ 10 мая 2010

На таком простом запросе я бы попытался выполнить его одним запросом. Издержки двух вызовов базы данных, вероятно, превысят дополнительное время обработки SQL из запроса.

Предложение UNION сделает это за вас:

SELECT id, someData1, someData2 
FROM Group 
WHERE id = 4
UNION 
SELECT id, someData, null 
FROM GroupMember 
WHERE group_id = 4; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...