При диагностике производительности запросов MySQL одной из первых вещей, которые вам нужно проанализировать, является отчет от EXPLAIN .
Если вы научитесь читать информацию, которую EXPLAIN дает вам, вы сможете увидеть, где запросы не используют индексы, или где они вызывают дорогие сортировки файлов или другие красные флажки производительности.
Я заметил, что в вашем запросе GROUP BY
не имеет значения, поскольку из KeywordRequests будет возвращена только одна пустая строка. Также ORDER BY
не имеет значения, так как вы упорядочиваете столбец, который всегда будет NULL из-за вашего условия WHERE
. Если вы удалите эти пункты, вы, вероятно, удалите сортировку файлов.
Также рассмотрите возможность переписать запрос в другие формы и измерить производительность каждой из них. Например:
SELECT k.id, k.keyword
FROM `keywords` AS k
WHERE NOT EXISTS (
SELECT * FROM `keywords_requests` AS kr
WHERE kr.keyword_id = k.id
AND kr.status IN ('success', 'active')
AND kr.source_id = '29'
AND kr.created > FROM_UNIXTIME(1234551323)
);
Другие советы:
- Является ли
kr.source_id
целым числом? Если это так, сравните с целым числом 29 вместо строки «29».
- Есть ли соответствующие индексы на
keyword_id
, status
, source_id
, created
? Возможно, лучше использовать даже составной индекс по всем четырем столбцам, поскольку MySQL будет использовать только один индекс на таблицу в данном запросе.
Вы сделали скриншот своего EXPLAIN вывода и разместили ссылку в комментариях. Я вижу, что запросом является , а не с использованием индекса из ключевых слов, что имеет смысл, так как в любом случае вы сканируете каждую строку в этой таблице. Фраза «Не существует» означает, что MySQL немного оптимизировал LEFT OUTER JOIN.
Я думаю, что это должно быть улучшено по сравнению с исходным запросом. Вероятно, GROUP BY / ORDER BY заставлял его сохранять промежуточный набор данных как временную таблицу и сортировать его на диск (что очень медленно!). То, что вы бы искали, это «Использование временного; использование файловой сортировки» в столбце «Дополнительные» информации EXPLAIN.
Так что, возможно, вы уже достаточно улучшили его, чтобы уменьшить узкое место.
Я заметил, что возможные ключи, вероятно, указывают, что у вас есть отдельные индексы в четырех столбцах. Вы можете улучшить это, создав составной индекс:
CREATE INDEX kr_cover ON keywords_requests
(keyword_id, created, source_id, status);
Вы можете дать MySQL подсказку для использования определенного индекса:
... FROM `keywords_requests` AS kr USE INDEX (kr_cover) WHERE ...