Почему дополнительный подзапрос для минимального идентификатора дает в 10 раз более быстрые результаты? - PullRequest
0 голосов
/ 22 декабря 2018

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

Этот запрос занимает около 10 с:

SELECT COUNT(DISTINCT i.id) AS count FROM
      items i
      INNER JOIN items_keywords ik ON ik.article_id = i.id AND ik.deleted = 0
      INNER JOIN category_keywords catk ON catk.keyword_id = ik.keyword_id
      INNER JOIN category cat ON cat.id = catk.category_id AND cat.customer_id = 968
      WHERE 
         i.deleted = 0 
         AND i.edited = 1 
         AND i.created >= '2018-12-18' 
         AND i.created <= '2018-12-20 23:59:59'

Объяснение:

enter image description here

Если добавить дополнительное условие where, устанавливающее минимальный идентификатор, это займет до 1 секунды:

AND i.id > (SELECT MIN(id) FROM items WHERE created >= '2018-12-01')

Объясните:

enter image description here

Протестировано с установкой диапазона i.id с подзапросом (удалено, создано в основном запросе и без предложения минимального идентификатора), потребовалось 10 секунд и объяснениеТо же, что и в первом запросе, за исключением строки подзапросов и отсутствия созданного индекса в основном запросе.

AND i.id IN (SELECT id FROM items WHERE created >= '2018-12-18' AND created <= '2018-12-20 23:59:59') #subquery takes 0,047s

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

Некоторые спецификации: Mysql: 5.6.4
таблица элементов: 22M строк
ключевые слова items: 120 миллионов строк
ключевые слова категорий: 70 миллионов строк

Это мой первый вопрос, поэтому не вините меня, но научите меня.

ДОБАВИТЬ:
Вот ШОУ CREATE TABLE для этих таблиц

1 Ответ

0 голосов
/ 22 декабря 2018

в 10 раз быстрее - похоже на разницу между данными, которые кэшируются в buffer_pool, а не нет.Вы дважды оценивали каждый запрос?

Пожалуйста, укажите SHOW CREATE TABLE для каждой таблицы;там может быть много тонких вещей.

Этот индекс может обмануть его первым:

INDEX(deleted, edited,  -- in either order
      created,          -- after those others
      id)               -- last

Этот индекс «покрывает», таким образом, давая дополнительный импульс.

В настоящее время оптимизатор решил начать с cat.customer_id = 968.

Если category_keywords является таблицей сопоставления многие: многие, см. this для несколькихСоветы по повышению производительности.

IN ( SELECT ... ) может быть слишком медленным.EXISTS ( SELECT ... ) может быть быстрее.

Если вы собираетесь переместить материал в подзапрос, поместите в него все i. тесты.Таким образом, он будет по существу похож на EXISTS и может использовать PRIMARY KEY(id) в качестве идеального индекса.(Дополнительный индекс не требуется.)

...