JOIN против SELECT IN при запросе произвольных связанных таблиц - PullRequest
0 голосов
/ 14 января 2020

При извлечении данных из нескольких таблиц для сопоставления с результатом GraphQL, что является более эффективным?

Псевдокод ниже.

Версия 1 - Объединение N таблиц и их разбор в отдельные объекты на стороне вызывающего абонента

alldata = SELECT a.*, b.*, c.*
    FROM aaaa a
    LEFT OUTER JOIN bbbb b on a.id = b.parent_id
    LEFT OUTER JOIN cccc c on b.id = c.parent_id
    WHERE a.name = 'my name';
/* Map flat DB rows to Java pojo-s */
aObj = parseRowsIntoJavaObjects(alldata)

Версия 2 - Выполнение выборок в таблицах 1 на 1, ограничение их идентификатором родительской строки

a_rows = SELECT a.* FROM aaaa a WHERE a.name = 'my name';
b_rows = SELECT b.* FROM bbbb b WHERE b.parent_id IN (a_rows.id);
c_rows = SELECT c.* FROM cccc c WHERE c.parent_id IN (b_rows.id);
/* Map flat DB rows to Java pojo-s */
bObj = parseRowsIntoJavaObjects(b_rows, c_rows);
aObj = parseRowsIntoJavaObjects(a_rows, bObj);

Таблицы связаны с использованием внешних ключей и могут иметь значения 1: 1, 1: N и N : N отношений. В противном случае их структура не определена - решение должно работать против произвольных моделей данных. Индексы могут быть добавлены по мере необходимости, и можно предположить, что для выполнения запроса имеются любые необходимые индексы.

Запрашиваемая, потому что таким способом может быть соединено любое количество таблиц, и я обеспокоен, если Версия 1 вызывает проблему необходимости возвращать одни и те же данные несколько раз в нескольких строках из-за того, что работают отношения «один к одному».

Я знаю, что выполнение нескольких запросов, как правило, плохая идея, если что-то может быть управляется с одним и IN () не особенно быстро. Использование IN здесь все еще плохая идея?

Поскольку решение должно быть обобщенным c и применяться к любому количеству моделей данных, я не хочу просто опробовать его и оптимизировать под конкретную c модель, как и большинство вопросов, касающихся JOIN ... WHERE IN () .. do. Я хотел бы спросить предложение о том, каков в целом более эффективный способ загрузки реляционных данных из произвольных иерархий до… скажем, глубины 3 уровня?

Единственный подобный вопрос, который я нашел на SO, имел дело с несколько иным случаем, но в своих ответах поддержал оба несколько похожих решения: Выбор из нескольких таблиц - отношение один ко многим

База данных: MariaDB

1 Ответ

1 голос
/ 14 января 2020

Это слишком долго для комментария.

Но вы должны извлекать данные в том формате, который вам нужен в вашем приложении. Если вам нужно три разных объекта в Java для As, Bs и Cs, то потяните данные три раза. Если вам нужен один объект, который объединяет атрибуты из таблиц, используйте один запрос с JOIN.

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

В этом случае у первого подхода есть недостатки. Одним из них является размер каждой строки - каждая строка содержит столбцы для B и C. Это занимает место, даже если значения NULL.

Большим недостатком является умножение результатов. Если для данной строки в A есть 10 совпадений в B и 20 совпадений в C, то ваш запрос вернет 200 строк для этого значения. Затем вам придется go через много дедупликации на стороне приложения.

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

...