Добавление индекса замедляет запрос - PullRequest
1 голос
/ 11 марта 2019

Я пытаюсь оптимизировать запрос

SELECT count(DISTINCT booking.id)
FROM ride 
       LEFT JOIN spot s1_ ON ride.from_spot_id = s1_.id
       LEFT JOIN spot s2_ ON ride.to_spot_id = s2_.id
       LEFT JOIN booking ON ride.booking_id = booking.id
       LEFT JOIN contact ON booking.contact_id = contact.id
WHERE (contact.first_name LIKE UPPER('%GAE%') OR contact.last_name LIKE UPPER('%GAE%') OR contact.email LIKE UPPER('%GAE%'))
  AND booking.paid_at IS NOT NULL
  AND booking.cancelled_at IS NULL;

Запрос выполнялся за 2 с или около того. Я добавил индекс на booking.cancelled_at

alter table booking add index booking_cancelled_at (cancelled_at);

И теперь это занимает около 15 секунд!

Я отправился на поиски и обнаружил, что, возможно, захочу добавить составной индекс для cancelled_at и paid_at. Я пытался это сделать, но MYSQL все еще выбирал индекс cancelled_at. Затем я пытаюсь удалить индекс cancelled_at для принудительного создания составного индекса. Мне было около 15 лет.

Вывод: без индекса 2 с индексом (одиночным или составным) 15 с.

Я посмотрел на планы:

с индексом With index

без индекса Without index

Я не уверен, почему полное сканирование быстрее, чем использование индекса?

Будем весьма благодарны за любые указания или указания, как решить эту проблему!

Спасибо

1 Ответ

0 голосов
/ 11 марта 2019

Для данного столбца вам нужно только проверить, является ли он null или нет, я не вижу смысла индексировать это.Вместо этого, поскольку booking.paid_at не должно быть null, я бы изменил join с booking и contact на inner join и использовал бы критерии, которые указаны для booking.paid и booking.cancelled_at.в критериях включения.

Пример:

SELECT count(DISTINCT booking.id)
FROM ride 
       JOIN booking ON ride.booking_id = booking.id
       AND booking.paid_at IS NOT NULL
       AND booking.cancelled_at IS NULL
       JOIN contact ON ON booking.contact_id = contact.id
       AND (contact.first_name LIKE UPPER('%GAE%') OR contact.last_name LIKE UPPER('%GAE%') OR contact.email LIKE UPPER('%GAE%'))
       LEFT JOIN spot s1_ ON ride.from_spot_id = s1_.id
       LEFT JOIN spot s2_ ON ride.to_spot_id = s2_.id;

Если он все еще медленный, вы можете предварительно выбрать идентификаторы contact перед запросом и использовать оператор in.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...