2011-04-12 9 views
10

Tengo que seleccionar algunas filas según una condición que no existe en una tabla. Si uso una unión como se muestra a continuación, se ejecuta en menos de 1 segundo.UNIÓN TODO frente a la condición OR en la consulta del servidor sql

SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(

SELECT 1 FROM TABLE t 
WHERE Data1 = t.Col1 AND Data2=t.Col2 

UNION ALL 

SELECT 1 FROM TABLE t 
WHERE Data1 = t.Col2 AND Data2=t.Col1 

) 

pero si uso una condición OR, se tarda cerca de un minuto como servidor SQL está haciendo una piscina perezosa mesa. ¿Alguien puede explicarlo?

SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(

SELECT 1 FROM TABLE t 
WHERE ((Data1 = t.Col1 AND Data2=t.Col2) OR (Data1 = t.Col2 AND Data2=t.Col1)) 
) 

Respuesta

2

El plan de consulta también se ve afectado por el número de filas en sus tablas. ¿Cuántas filas hay en la tabla t?

También puede probar:

SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(
    SELECT 1 FROM TABLE t 
    WHERE Data1 = t.Col1 AND Data2=t.Col2 
) 
AND NOT EXISTS 
( 
    SELECT 1 FROM TABLE t 
    WHERE Data1 = t.Col2 AND Data2=t.Col1  
) 

o (corregido para SQL-Server) este que va a utilizar el índice:

WITH tt AS        <---- a temp table with 2 rows 
(SELECT Data1 AS Col1, Data2 AS Col2 
    UNION 
    SELECT Data2 AS Col1, Data1 AS Col2 
) 
SELECT 1 FROM dummyTable 
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM TABLE t 
    JOIN tt      
     ON tt.Col1 = t.Col1 AND tt.Col2=t.Col2 
) 
+0

La tabla tiene como 800k filas en ella. Me gustan las opciones que me has proporcionado. Actualmente estoy usando el sindicato, pero también podría usar la opción AND NOT EXISTS. Principalmente estaba buscando ver por qué "O" tendría un problema. Supongo que no está usando ningún índice y tiene que almacenar los valores en una tabla temporal para comparar. –

+0

No espero que mi solución 'AND NOT EXISTS' sea mejor que la' UNION'. (por cierto, ¿por qué usas 'UNION ALL' y no' UNION'? –

+0

Creo que la unión es más rápida ya que no hace ningún agrupamiento/filtrado. En mi caso, va a ser una condición mutuamente excluyente así que puede hacer una unión de todo. Y sí, no creo Y no existe funcionará mejor que Union All, solo lee mejor. –

1

El uso de la OR es, probablemente, causando el optimizador de consultas utilizar ya no es un índice en la segunda consulta. Mire la explicación para cada consulta y eso le dirá la respuesta.

+0

puede que tengas razón. Es un tipo de consulta recursiva y el plan de ejecución es complicado. No es fácil decir nada de eso. La mayoría del plan se ve idéntico para ambas consultas. Supongo que seguiré adelante y usaré UNION ALL. –

4

La cuestión es que se está especificando dos condiciones con OR que aplicar a tablas separadas en su consulta. Debido a esto, la búsqueda del índice no agrupado debe devolver la mayoría o todas las filas en su tabla grande porque la lógica O significa que también pueden coincidir con la cláusula de condición en la segunda tabla.

Observe el plan de ejecución de SQL en los tres ejemplos anteriores y observe el número de filas que salen del índice no agrupado en la gran tabla. El resultado final solo puede devolver 1,000 o menos de las 800,000 filas en la tabla, pero la cláusula OR significa que el contenido de esa tabla debe ser referenciado con el condicional en la segunda tabla ya que O significa que pueden ser necesarios para la final salida de consulta

Dependiendo de su plan de ejecución, la búsqueda de índice puede extraer las 800,000 filas de la tabla grande porque también pueden coincidir con las condiciones de la cláusula O de la segunda tabla. El UNION ALL es una consulta separada contra una tabla cada una, por lo que la búsqueda de índice solo tiene que generar el conjunto de resultados más pequeño que pueda coincidir con la condición para esa consulta.

Espero que esto tenga sentido. Me encontré con la misma situación mientras refactorizaba las declaraciones SQL de ejecución lenta.

Saludos,

Andre Ranieri

Cuestiones relacionadas