mysql - SQL Performance UNION vs OR
(5)
Depende de lo que el optimizador termine haciendo en función del tamaño de los datos, índices, versión de software, etc.
Supongo que usar OR le daría al optimizador una mejor oportunidad de encontrar algunas eficiencias, ya que todo está en una sola declaración lógica.
Además, UNION tiene algunos gastos generales, ya que crea un conjunto de restablecimiento (sin duplicados). Cada declaración en la UNIÓN debería ejecutarse bastante rápido si la compañía está indexada ... no estoy seguro de que realmente esté haciendo el doble de trabajo.
Línea de fondo
A menos que realmente tenga una gran necesidad de exprimir al máximo su consulta, probablemente sea mejor ir con la forma que mejor comunica su intención ... el O
Actualizar
También quise mencionar IN. Creo que la siguiente consulta dará un mejor rendimiento que el OR (también es la forma que prefiero):
select username from users where company in (''bbc'', ''itv'');
Acabo de leer parte de un artículo de optimización y segfaulted en la siguiente declaración:
Cuando se utilizan sentencias SQL replace utilizando
OR
conUNION
:
select username from users where company = ‘bbc’ or company = ‘itv’;
a:
select username from users where company = ‘bbc’ union select username from users where company = ‘itv’;
De una EXPLAIN
rápida:
Usando OR
:
Usando UNION
:
¿Esto no significa que UNION
hace el doble del trabajo ?
Si bien aprecio que UNION
puede ser más eficaz para ciertos RDBMS y ciertos esquemas de tabla, esto no es categóricamente cierto como las sugerencias del autor.
Pregunta
¿Me equivoco?
En casi todos los casos, la union
o union all
versiones hará dos escaneos de tablas completas de la tabla de usuarios.
La versión or
es mucho mejor en la práctica, ya que solo escaneará la tabla una vez. También usará un índice solo una vez, si está disponible.
La afirmación original simplemente parece incorrecta, para casi cualquier base de datos y cualquier situación.
Esas no son la misma consulta.
No tengo mucha experiencia con MySQL, por lo que no estoy seguro de qué hace o no el optimizador de consultas, pero estos son mis pensamientos desde mi experiencia general (principalmente el servidor ms sql).
Normalmente, el analizador de consultas puede tomar las dos consultas anteriores y hacer exactamente el mismo plan (si fueran iguales), por lo que no tendría importancia. Sospecho que no hay diferencia de rendimiento entre estas consultas (que son equivalentes)
select distinct username from users where company = ‘bbc’ or company = ‘itv’;
y
select username from users where company = ‘bbc’
union
select username from users where company = ‘itv’;
Ahora, la pregunta es, ¿habría una diferencia entre las siguientes consultas, de las que en realidad no sé, pero sospecho que el optimizador lo haría más como la primera consulta
select username from users where company = ‘bbc’ or company = ‘itv’;
y
select username from users where company = ‘bbc’
union all
select username from users where company = ‘itv’;
La respuesta de Bill Karwin es bastante correcta. Cuando ambas partes de la declaración OR tienen su propio índice, es mejor hacer la unión porque una vez que tienes un pequeño subconjunto de resultados, es más fácil ordenarlos y eliminar duplicados. El costo total es casi menor que usar solo un índice (para uno de la columna) y escaneo de tabla para la otra columna (porque mysql solo usa un índice para una columna).
Depende de la estructura de la mesa y las necesidades en general, pero en grandes mesas la unión me dio mejores resultados.
O el artículo que leíste utilizó un mal ejemplo o malinterpretaste su punto.
select username from users where company = ''bbc'' or company = ''itv'';
Esto es equivalente a:
select username from users where company IN (''bbc'', ''itv'');
MySQL puede usar un índice en la company
para esta consulta muy bien. No hay necesidad de hacer ninguna UNIÓN.
El caso más complicado es cuando tiene una condición OR
que implica dos columnas diferentes .
select username from users where company = ''bbc'' or city = ''London'';
Supongamos que hay un índice en la company
y un índice separado en la city
. Dado que MySQL usualmente usa solo un índice por tabla en una consulta dada, ¿qué índice debería usar? Si usa el índice en la company
, aún tendría que hacer un escaneo de tabla para encontrar las filas donde la city
es Londres. Si usa el índice en la city
, tendría que hacer un escaneo de tabla para las filas donde la company
es BBC.
La solución UNION
es para este tipo de casos.
select username from users where company = ''bbc''
union
select username from users where city = ''London'';
Ahora cada subconsulta puede usar el índice para su búsqueda, y los resultados de la subconsulta son combinados por UNION
.
Un usuario anónimo propuso editar mi respuesta anterior, pero un moderador rechazó la edición. Debería haber sido un comentario, no una edición. El reclamo de la edición propuesta fue que UNION debe ordenar el conjunto de resultados para eliminar las filas duplicadas. Esto hace que la consulta se ejecute más lentamente, y la optimización del índice es, por lo tanto, un lavado.
Mi respuesta es que los índices ayudan a reducir el conjunto de resultados a un pequeño número de filas antes de que ocurra la UNIÓN. UNION elimina los duplicados, pero para hacerlo solo tiene que ordenar el pequeño conjunto de resultados. Puede haber casos en los que las cláusulas WHERE coincidan con una parte significativa de la tabla, y la clasificación durante UNION es tan costosa como simplemente hacer el escaneo de tabla. Pero es más común que las búsquedas indexadas reduzcan el conjunto de resultados, por lo que la clasificación es mucho menos costosa que la exploración de tabla.
La diferencia depende de los datos en la tabla y de los términos que se buscan. La única forma de determinar la mejor solución para una consulta determinada es probar ambos métodos en el generador de perfiles de consultas MySQL y comparar su rendimiento.