MySQL в предложении медленный с 10 или более элементами - PullRequest
0 голосов
/ 25 апреля 2018

Этот запрос занимает 18 секунд

SELECT `wd`.`week` AS `start_week`, `wd`.`hold_code`, COUNT(wd.hold_code) AS hold_code_count
FROM `weekly_data` AS `wd`
JOIN aol_reporting_hold_codes hc ON hc.hold_code = wd.hold_code AND chart = 'GR'
WHERE `wd`.`days` <= 6 
AND `wd`.`hold_code` IS NOT NULL 
AND NOT `wd`.`hold_code` = '' 
AND `wd`.`week` >= '201717' 
AND `wd`.`itemgroup` IN ('BOTDTO', 'BOTDWG', 'C&FORG', 'C&FOTO', 'MF-SUB', 'MI-SUB', 'PROPRI', 'PROPTO', 'STRSTO', 'STRSUB') 
AND `production_type` = 2
AND `contract` = "1234"
AND `project` = 8
GROUP BY `start_week`, `wd`.`hold_code`

Этот запрос занимает 4 секунды

SELECT `wd`.`week` AS `start_week`, `wd`.`hold_code`, COUNT(wd.hold_code) AS hold_code_count
FROM `weekly_data` AS `wd`
JOIN aol_reporting_hold_codes hc ON hc.hold_code = wd.hold_code AND chart = 'GR'
WHERE `wd`.`days` <= 6 
AND `wd`.`hold_code` IS NOT NULL 
AND NOT `wd`.`hold_code` = '' 
AND `wd`.`week` >= '201717' 
AND `wd`.`itemgroup` IN ('BOTDWG', 'C&FORG', 'C&FOTO', 'MF-SUB', 'MI-SUB', 'PROPRI', 'PROPTO', 'STRSTO', 'STRSUB') 
AND `production_type` = 2
AND `contract` = "1234"
AND `project` = 8
GROUP BY `start_week`, `wd`.`hold_code`

Все, что я сделал, это удалил один элемент из предложения IN. Я могу удалить любой из предметов. Он работает в течение 4 секунд, пока есть 9 пунктов или меньше. Запуск увеличится до 10 пунктов, если потребуется 18 секунд.

Я думал, что MySQL ограничил длину команды размером, т. Е. 1 МБ

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Больше, чем просто EXPLAIN, используйте EXPLAIN FORMAT=JSON и получите «трассировку оптимизатора» для запроса.Я подозреваю, что длина IN приводит к выбору другого плана запроса.

Количество элементов в IN практически не ограничено.Я видел целых 70 тыс.

Кроме того, вы можете ускорить даже 4-секундную версию ...

Я предлагаю иметь этот индекс.Гррр ... Я не могу сказать, какие столбцы в каких таблицах.Итак, если все они находятся в одной таблице, то создайте такой индекс:

INDEX(production_type, contract, project) -- in any order

Если все они находятся в wd, то добавьте 4-й столбец - любой из week, itemgroup, days.

Будьте осторожны с COUNT(wd.hold_code).

  • COUNT(x) проверяет x на отсутствие-NULL;Это то что ты хочешь?Если нет, то просто скажите COUNT(*).
  • Когда JOINing, тогда GROUP BY, вы получите «взорваться-взорваться».Количество промежуточных рядов велико;то есть когда COUNT выполняется.
  • Кажется неправильным как для COUNT(hold_code), так и GROUP BY hold_code.Что вы пытаетесь сделать?

Для дальнейшего обсуждения, пожалуйста, укажите SHOW CREATE TABLE и EXPLAIN.

0 голосов
/ 25 апреля 2018

Обратите внимание, что ограничение предложения MySql IN устанавливается значением max_allowed_packet.Вы можете проверить с помощью NOT IN, если результаты быстрее.Также я предлагаю поместить значения, которые будут проверяться с предложением IN, под строкой буфера вместо значений, разделенных запятыми, а затем попробовать.

...