MySQL, как и все другие системы, кроме SQL Server, может оптимизировать LEFT JOIN
/IS NULL
вернуть, FALSE
как только будет найдено соответствующее значение, и это единственная система, которая заботилась о документировании этого поведения. […] Поскольку MySQL не способен использовать алгоритмы HASH
и MERGE
объединять их, единственное, на что ANTI JOIN
он способен, этоNESTED LOOPS ANTI JOIN
[...]
По сути, [ NOT IN
] - это тот же план, который LEFT JOIN
/ IS NULL
использует, несмотря на то, что эти планы выполняются разными ветвями кода и в результатах они выглядят по-разному EXPLAIN
. Алгоритмы фактически одинаковы, и запросы выполняются в одно и то же время.
[...]
Трудно сказать точную причину [падения производительности при использовании NOT EXISTS
] , поскольку это падение является линейным и, по-видимому, не зависит от распределения данных, количества значений в обеих таблицах и т. Д., Пока оба поля проиндексированы. Поскольку в MySQL есть три фрагмента кода, которые по существу выполняют одну работу, вполне возможно, что код, отвечающий за него, EXISTS
выполняет какую-то дополнительную проверку, которая требует дополнительного времени.
[...]
MySQL может оптимизировать все три метода NESTED LOOPS ANTI JOIN
. […] Однако эти три метода генерируют три разных плана, которые выполняются тремя разными частями кода. Код, который выполняет EXISTS
предикат, примерно на 30% менее эффективен […]
Вот почему лучший способ поиска пропущенных значений в MySQL - использовать LEFT JOIN
/ IS NULL
или NOT IN
вместо NOT EXISTS
.
(выделено)