Странно медленный запрос Mysql на ИЛИ

У меня есть следующий запрос, который занимает 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 только для отладки

пожалуйста, уточните свое условие, чтобы избежать двусмысленности ( пользователь ИЛИ ( партнер и частный )) --ИЛИ-- (( пользователь или партнер ) и частный).

DRapp 09.05.2022 19:16

После того, как вы сделали это, и это все еще медленно: вполне законно взять два быстрых запроса и использовать UNION для их объединения. Иногда лучше избегать OR, потому что OR может затруднить для механизма БД выбор индекса для запроса.

Tomalak 09.05.2022 19:20

показать как запрос CREATE TABLE, чтобы увидеть, какой индекс создан

Bernd Buffen 09.05.2022 19:26
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
3
47
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  • 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 мс. Другие индексы уже присутствовали.
Christian Willing 10.05.2022 11:55

Другие вопросы по теме