Mas no exemplo, a primeira consulta tem uma condição na coluna
a
, enquanto a segunda consulta tem uma condição na coluna b
. Isso provavelmente veio de uma consulta difícil de otimizar:SELECT * FROM mytable WHERE a=X OR b=Y
Essa consulta é difícil de otimizar com indexação simples de árvore B. O mecanismo pesquisa um índice na coluna
a
? Ou na coluna b
? De qualquer forma, pesquisar o outro termo requer uma varredura de tabela. Daí o truque de usar UNION para separar em duas consultas para um termo cada. Cada subconsulta pode usar o melhor índice para cada termo de pesquisa. Em seguida, combine os resultados usando UNION.
Mas os dois subconjuntos podem se sobrepor, porque algumas linhas em que
b=Y
também pode ter a=X
nesse caso, essas linhas ocorrem em ambos os subconjuntos. Portanto, você tem que fazer a eliminação de duplicatas, ou então ver algumas linhas duas vezes no resultado final. SELECT * FROM mytable WHERE a=X
UNION DISTINCT
SELECT * FROM mytable WHERE b=Y
UNION DISTINCT
é caro porque implementações típicas classificam as linhas para encontrar duplicatas. Assim como se você usar SELECT DISTINCT ...
. Também temos a percepção de que é um trabalho ainda mais "desperdiçado" se os dois subconjuntos de linhas que você está unindo tiverem muitas linhas ocorrendo em ambos os subconjuntos. São muitas filas para eliminar.
Mas não há necessidade de eliminar duplicatas se você puder garantir que os dois conjuntos de linhas já sejam distintos. Ou seja, se você garantir que não há sobreposição. Se você puder confiar nisso, será sempre impossível eliminar duplicatas e, portanto, a consulta pode pular essa etapa e, portanto, pular a classificação dispendiosa.
Se você alterar as consultas para garantir que elas selecionem subconjuntos de linhas sem sobreposição, isso é uma vitória.
SELECT * FROM mytable WHERE a=X
UNION ALL
SELECT * FROM mytable WHERE b=Y AND a!=X
Esses dois conjuntos são garantidos para não ter sobreposição. Se o primeiro conjunto tiver linhas onde
a=X
e o segundo conjunto tem linhas onde a!=X
então não pode haver nenhuma linha que esteja em ambos os conjuntos. A segunda consulta, portanto, apenas captura algumas das linhas em que
b=Y
, mas qualquer linha onde a=X AND b=Y
já está incluído no primeiro conjunto. Assim, a consulta obtém uma pesquisa otimizada para dois
OR
termos, sem produzir duplicatas e sem exigir UNION DISTINCT
Operação.