Оптимизация INNER JOIN для нескольких таблиц - PullRequest
0 голосов
/ 24 мая 2019

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

У меня есть одна таблица со 100k + строками и около 30 столбцами, из которых я могу отфильтровать до 3-х строк (в этом примере), а затем выполнить INNER JOIN s для 21 маленькой справочной таблицы.

В моей первой попытке я был ленив и использовал неявные соединения.

SELECT `master_table`.*, `lookup_table`.`data_point` x 21
FROM `lookup_table` x 21
WHERE `master_table`.`indexed_col` = "value"
AND `lookup_table`.`id` = `lookup_col` x 21

Время запроса истекло:

#2013 - Lost connection to MySQL server during query

После этого я попытался объяснить соединения.

SELECT `master_table`.*, `lookup_table`.`data_point` x 21
FROM `master_table`
INNER JOIN `lookup_table` ON `lookup_table`.`id` = `master_table`.`lookup_col` x 21
WHERE `master_table`.`indexed_col` = "value"

Тем не менее получил тот же результат. Затем я понял, что запрос, вероятно, сначала пытается выполнить объединения, а затем выполнить фильтрацию с помощью предложения WHERE. Поэтому после небольшого исследования я узнал, как можно применить подзапрос, чтобы сначала выполнить фильтр, а затем выполнить объединения для вновь созданной таблицы. Это то место, куда я попал, и он по-прежнему возвращает ту же ошибку. Можно ли как-нибудь улучшить этот запрос?

SELECT `temp_table`.*, `lookup_table`.`data_point` x 21
FROM (SELECT * FROM `master_table` WHERE `indexed_col` = "value") as `temp_table`
INNER JOIN `lookup_table` ON `lookup_table`.`id` = `temp_table`.`lookup_col` x 21

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

Ответы [ 2 ]

2 голосов
/ 24 мая 2019

Во-первых, в самом простом аспекте вы ищете

select
      mt.*
   from
      Master_Table mt
   where
      mt.indexed_col = 'value'

Это, вероятно, мгновенно, если у вас есть индекс на вашей главной таблице на указанном indexed_col в первой позиции (в случае, если у вас былсоставной индекс многих полей)…

Теперь, если я правильно понимаю вас в ваших разных столбцах поиска (всего 21), вы только что упростили их для избыточности в этом посте, но на самом деле делаете что-то в результатеиз

select
      mt.*,
      lt1.lookupDescription1,
      lt2.lookupDescription2,
      ...
      lt21.lookupDescription21
   from
      Master_Table mt
         JOIN Lookup_Table1 lt1
            on mt.lookup_col1 = lt1.pk_col1
         JOIN Lookup_Table2 lt2
            on mt.lookup_col2 = lt2.pk_col2
         ...
         JOIN Lookup_Table21 lt21
            on mt.lookup_col21 = lt21.pk_col21
   where
      mt.indexed_col = 'value'

У меня был проект, который более десяти лет назад имел дело с аналогичной ситуацией ... В мастер-таблице было около 21+ миллионов записей, и мне нужно было объединить около 30+ справочных таблиц.Система сканировала и запрашивала, умерла после выполнения запроса более чем через 24 часа.

Это также было на сервере MySQL, и исправлением было одно ключевое слово MySQL ...

Select STRAIGHT_JOIN mt.*, ...

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

ПопробуйтеКлючевое слово STRAIGHT_JOINОн взял запрос, над которым я работал, и завершил его примерно за 1,5 часа ... он возвращал все 21 миллион строк со всеми соответствующими описаниями ключей поиска для окончательного вывода, следовательно, все еще требовалось больше времени, чем всего 3 записи.

0 голосов
/ 24 мая 2019

Во-первых, не используйте подзапрос.Напишите запрос следующим образом:

SELECT mt.*, lt.`data_point`
FROM `master_table` mt INNER JOIN
     `lookup_table` l
     ON l.`id` = mt.`lookup_col`
WHERE mt.`indexed_col` = value;

Нужные индексы: master_table(value, lookup_col) и lookup_table(id, data_point).

Если проблемы с производительностью по-прежнему сохраняются, существует несколько возможностей.Среди них есть и то, что набор результатов слишком велик, чтобы его можно было вернуть за разумное время.Чтобы проверить, так ли это, вы можете использовать select count(*) для подсчета количества возвращаемых строк.

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