Но в примера първата заявка има условие за колона a
, докато втората заявка има условие за колона b
. Това вероятно идва от заявка, която е трудна за оптимизиране:
SELECT * FROM mytable WHERE a=X OR b=Y
Тази заявка е трудна за оптимизиране с просто индексиране на B-дърво. Двигателят търси ли индекс в колона a
? Или в колона b
? Така или иначе, търсенето на другия термин изисква сканиране на таблица.
Оттук и трикът за използване на UNION за разделяне на две заявки за по един термин всяка. Всяка подзаявка може да използва най-добрия индекс за всяка дума за търсене. След това комбинирайте резултатите с помощта на UNION.
Но двете подмножества може да се припокриват, защото някои редове са b=Y
може също да има a=X
в този случай такива редове се срещат и в двете подмножества. Следователно трябва да направите дублиране на елиминиране или да видите някои редове два пъти в крайния резултат.
SELECT * FROM mytable WHERE a=X
UNION DISTINCT
SELECT * FROM mytable WHERE b=Y
UNION DISTINCT
е скъпо, защото типичните реализации сортират редовете, за да намерят дубликати. Точно както ако използвате SELECT DISTINCT ...
.
Също така имаме схващането, че е още по-„загубена“ работа, ако двете подмножества от редове, които обединявате, имат много редове, които се срещат и в двете подмножества. Има много редове за премахване.
Но няма нужда да премахвате дубликати, ако можете да гарантирате, че двата набора от редове вече са различни. Тоест, ако гарантирате, че няма припокриване. Ако можете да разчитате на това, елиминирането на дубликати винаги би било безоперативен и следователно заявката може да пропусне тази стъпка и следователно да пропусне скъпото сортиране.
Ако промените заявките, така че те да са гарантирани, че избират неприпокриващи се подмножества от редове, това е печалба.
SELECT * FROM mytable WHERE a=X
UNION ALL
SELECT * FROM mytable WHERE b=Y AND a!=X
Гарантирано е, че тези два комплекта нямат припокриване. Ако първият набор има редове, където a=X
а вторият набор има редове, където a!=X
тогава не може да има ред, който да е и в двата набора.
Следователно втората заявка улавя само някои от редовете, където b=Y
, но всеки ред, където a=X AND b=Y
вече е включено в първия комплект.
Така заявката постига оптимизирано търсене за две OR
термини, без да създават дубликати и не изискват UNION DISTINCT
операция.