Используйте EXPLAIN
, чтобы увидеть план выполнения.
В запросе уже используется шаблон предотвращения объединения для b
.
Я рекомендую использовать тот же шаблон анти-объединения вместо проверки NOT IN
. (Большой горб с анти-объединением, кажется, обволакивает наш мозг; как только мы поймем схему, мы сможем ее использовать.
Примерно так:
SELECT a.ticketnumber
FROM ticket_updates a
-- anti-join
LEFT
JOIN ticket_updates b
ON b.ticketnumber = a.sequence
AND b.type = 'reminder_complete'
-- anti-join
LEFT
JOIN ticket_updates c
ON c.ticketnumber = a.ticketnumber
AND c.type = 'reminder_complete'
--
WHERE c.ticketnumber IS NULL
AND b.ticketnumber IS NULL
--
AND a.type IN ('reminder','reminder_high')
AND a.for_agent IN ('','2')
AND a.notes <= '2018-05-10 23:00:00'
Что касается производительности, нам нужно обеспечить наличие подходящих индексов.
Учитывая, что NOT IN (correlated subquery)
вносит вклад во время выполнения, замена его на анти-объединение повышает вероятность того, что MySQL будет использовать подходящий индекс, если он доступен. (С точки зрения производительности, эти повторные выполнения коррелированного подзапроса съедят наш обед и нашу коробку с обедом, если мы не будем осторожны.)
Опять же, используйте EXPLAIN
, чтобы увидеть план выполнения.
Шаблон против объединения можно заменить на NOT EXISTS
, чтобы получить эквивалентный план. (Интуитивно счётчик, шаблон анти-объединения иногда показывает «не существует» в столбце «Extra» выходных данных «EXPLAIN», а NOT NOT EXISTS - нет.)
Я ожидаю, что это даст план выполнения, который почти эквивалентен:
SELECT a.ticketnumber
FROM ticket_updates a
WHERE a.type IN ('reminder','reminder_high')
AND a.for_agent IN ('','2')
AND a.notes <= '2018-05-10 23:00:00'
AND NOT EXISTS
( SELECT 1
FROM ticket_updates b
WHERE b.ticketnumber = a.sequence
AND b.type = 'reminder_complete'
)
AND NOT EXISTS
( SELECT 1
FROM ticket_updates c
WHERE c.ticketnumber = a.ticketnumber
AND c.type = 'reminder_complete'
)