sql >> Base de Datos >  >> RDS >> Mysql

SQL UNION ALL para eliminar duplicados

Pero en el ejemplo, la primera consulta tiene una condición en la columna a , mientras que la segunda consulta tiene una condición en la columna b . Esto probablemente vino de una consulta que es difícil de optimizar:

SELECT * FROM mytable WHERE a=X OR b=Y

Esta consulta es difícil de optimizar con una indexación de árbol B simple. ¿El motor busca un índice en la columna a? ? O en la columna b ? De cualquier manera, buscar el otro término requiere un escaneo de tabla.

De ahí el truco de usar UNION para separar en dos consultas para un término cada una. Cada subconsulta puede utilizar el mejor índice para cada término de búsqueda. Luego combine los resultados usando UNION.

Pero los dos subconjuntos pueden superponerse, porque algunas filas donde b=Y también puede tener a=X en cuyo caso tales filas ocurren en ambos subconjuntos. Por lo tanto, debe realizar una eliminación por duplicado o ver algunas filas dos veces en el resultado final.

SELECT * FROM mytable WHERE a=X 
UNION DISTINCT
SELECT * FROM mytable WHERE b=Y

UNION DISTINCT es costoso porque las implementaciones típicas ordenan las filas para encontrar duplicados. Al igual que si usa SELECT DISTINCT ... .

También tenemos la percepción de que es aún más trabajo "desperdiciado" si los dos subconjuntos de filas que está uniendo tienen muchas filas en ambos subconjuntos. Son muchas filas para eliminar.

Pero no hay necesidad de eliminar los duplicados si puede garantizar que los dos conjuntos de filas ya son distintos. Es decir, si garantiza que no hay superposición. Si puede confiar en eso, entonces siempre sería imposible eliminar los duplicados y, por lo tanto, la consulta puede omitir ese paso y, por lo tanto, omitir la clasificación costosa.

Si cambia las consultas para garantizar que seleccionen subconjuntos de filas que no se superponen, eso es una victoria.

SELECT * FROM mytable WHERE a=X 
UNION ALL 
SELECT * FROM mytable WHERE b=Y AND a!=X

Estos dos conjuntos están garantizados para no tener superposición. Si el primer conjunto tiene filas donde a=X y el segundo conjunto tiene filas donde a!=X entonces no puede haber ninguna fila que esté en ambos conjuntos.

Por lo tanto, la segunda consulta solo detecta algunos de las filas donde b=Y , pero cualquier fila donde a=X AND b=Y ya está incluido en el primer conjunto.

Entonces la consulta logra una búsqueda optimizada para dos OR términos, sin producir duplicados y sin requerir UNION DISTINCT operación.