У меня есть следующий запрос, который занимает 3 секунды
SELECT SQL_NO_CACHE e.Id
FROM `Email` e
LEFT JOIN basedb.emailconnections ec ON ec.id = e.EmailConnectionId
LEFT JOIN historydb.`event` ev ON ev.EmailId = e.Id
Where e.UserId = 228
OR ev.PartnerId = 150
AND ev.Private = 0;
проблема исходит от (e.UserId = 228 OR ev.PartnerId = 150 AND ev.Private = 0)
если я запускаю только левую часть из WHERE вот так, это занимает 0,04 секунды
SELECT SQL_NO_CACHE e.Id
FROM `Email` e
LEFT JOIN basedb.emailconnections ec ON ec.id = e.EmailConnectionId
LEFT JOIN historydb.`event` ev ON ev.EmailId = e.Id
Where e.UserId = 228;
и если я запускаю правильную часть вот так, это занимает 0,03 секунды
SELECT SQL_NO_CACHE e.Id
FROM `Email` e
LEFT JOIN basedb.emailconnections ec ON ec.id = e.EmailConnectionId
LEFT JOIN historydb.`event` ev ON ev.EmailId = e.Id
Where ev.PartnerId = 150
AND ev.Private = 0;
так что это намного быстрее, если я запускаю 2 запроса вместо запуска одного, а количество результатов от двух более быстрых раз совпадает с медленным
SQL_NO_CACHE только для отладки
После того, как вы сделали это, и это все еще медленно: вполне законно взять два быстрых запроса и использовать UNION для их объединения. Иногда лучше избегать OR, потому что OR может затруднить для механизма БД выбор индекса для запроса.
показать как запрос CREATE TABLE, чтобы увидеть, какой индекс создан






AND обычно быстрее, чем OR.
Сначала будут использованы тесты для одной таблицы, затем она "присоединится" к другой таблице и отфильтрует по ней. Это ограничивает эффективность JOIN и WHERE.
Проверь это;
Where e.UserId = 228
OR ev.PartnerId = 150
AND ev.Private = 0;
такой же как
Where e.UserId = 228
OR ( ev.PartnerId = 150 AND ev.Private = 0 );
Если это не то, что вы хотели, измените скобки.
Эти индексы могут помочь с первым запросом (со скобками И/ИЛИ, как указано):
e: INDEX(UserId, EmailConnectionId, Id)
ev: INDEX(EmailId)
Как упоминалось в комментариях, UNION часто помогает ускорить OR.
UNION не помогло, может быть, на 100 мс быстрее, но все же более 3 секунд. добавление INDEX(UserId, EmailConnectionId, Id) помогло сократить время примерно до 500 мс. Другие индексы уже присутствовали.
пожалуйста, уточните свое условие, чтобы избежать двусмысленности ( пользователь ИЛИ ( партнер и частный )) --ИЛИ-- (( пользователь или партнер ) и частный).