2012-06-13 18 views
34

Tengo un código .NET que comprueba la existencia de un registro SQL a un intervalo moderadamente alto. Estoy buscando hacer esta verificación como "barata" . como sea posible"SELECCIONAR SUPERIOR 1 1" VS "SI EXISTE (SELECCIONAR 1"

me pregunto las características de dos consultas:

IF EXISTS(SELECT 1 
      FROM BigTable 
      WHERE SomeColumn = 200) 
    SELECT 1 AS FOUND 
ELSE 
    SELECT 0 AS FOUND 

VS

SELECT TOP 1 1 
FROM BigTable 
WHERE SomeColumn = 200 

ambos producen planes de ejecución similares pero la parte superior SELECT 1 1 parece ejecutará más rápido.: Menos consulta para analizar y cuándo registro no se encuentra, envía menos por la tubería. También supongo que funciona más rápido en el cliente porque solo necesito verificar el recuento de registros, en lugar de calcular el valor de retorno de IF EXISTS.

La mayoría de los beneficios de rendimiento son insignificantes. Pero si ambos devuelven constantemente el mismo resultado, ¿por qué no elegir el método ligeramente más rápido?

¿Es "SELECT TOP 1 1" la mejor manera de verificar la existencia de un registro en .NET?

(Usamos .NET 3.5, y estoy tratando de evitar LINQ porque no se usa en ninguna otra parte de la aplicación. También tenemos algunas aplicaciones heredadas de VB6 que estamos migrando/reescribiendo, por lo que es posible que necesiten ejecutar esto como bien.)

EDIT: Solo un poco más de detalle en el diseño. Este registro es un "encabezado". Hay otra tabla que tiene registros secundarios que se leerán/analizarán cuando se encuentre este encabezado. La falta de un registro es algo bueno: no hay trabajo que hacer.

EDIT2: La falta de un registro que cumpla la condición se producirá con más frecuencia. Vienen en ondas esporádicas.

+0

No funciona cuando no hay filas que cumplan las condiciones. Pruebe 'SELECCIONAR TOP 1 1 FROM BigTable donde 1 = 0' –

+0

Ese es el punto. Estoy comprobando la existencia de una fila que cumple con la condición. –

+1

Después de "EDITAR": ¿Por qué está comprobando la existencia del registro en lugar de tratar de obtener un solo registro que coincida con sus criterios? Si fetch (select) no devuelve ningún registro, no tiene trabajo que hacer y no es mucho más caro que solo verificar la existencia de dicho registro. Si devuelve registro, tiene cargados sus datos de encabezado y acaba de guardar una consulta de base de datos. –

Respuesta

31

Recomendaría IF EXISTS(SELECT * ...), a menos que esto esté causando un problema de rendimiento. Expresa el intento de la consulta de una manera mucho mejor entendida que las alternativas.

Evitaría COUNT(*) (como en las respuestas actuales) a menos que realmente necesite el recuento de filas de la tabla.

Si desea que la "eficiencia" de comprobar el recuento de filas del resultado, probablemente me vaya para:

select 1 where exists(select * from BigTable where SomeColumn=200) 

que produce el mismo resultado en forma de su segunda consulta (0 o 1 fila)

+3

Absolutamente de acuerdo. Parece obvio, pero aclararle al optimizador lo que estamos tratando de hacer (verificar si algo existe) suele ser el primer paso para lograr un rendimiento sensato. –

+0

¡Esto se ve genial! Pero "SELECT TOP 1 1" todavía es ligeramente más rápido en el plan de ejecución real. Tal vez si esto fue en un procedimiento? –

+0

@EricSwanson - eso puede deberse a todo tipo de detalles en la configuración de su servidor (en términos de hardware, software y uso, qué tan grande es la tabla real, qué índices están disponibles, etc.). Acabo de realizar algunas pruebas en una mesa de tamaño moderado y no pude dividir la diferencia entre ellos. –

-11

no está seguro acerca de SQL Server pero en otras bases de datos es el método estándar:

SELECT COUNT(*) FROM BigTable where SomeCol = 200; 

La eficiencia real depende de ti índices etc.

+10

Si solo te preocupa la existencia/inexistencia de filas, te advertiría explícitamente * en contra de * usar 'COUNT (*) ', ya que tiene que procesar la tabla * completa * para calcular el resultado (mientras que' TOP 1' o 'EXISTS' pueden detenerse después de que se haya encontrado una sola fila coincidente) –

+3

De acuerdo con @Damien_The_Unbeliever - nunca debe usar un "contar" si solo le preocupa "existe" - eso causa trabajo adicional –

9

Esto es lo que desea en lugar de la instrucción IF

SELECT ISNULL(
    (SELECT TOP 1 1 FROM BigTable where SomeCol = 200), 0); 
1

Sin duda para la segunda opción:

SELECT TOP 1 1 
FROM BigTable 
WHERE SomeColumn = 200 

el plan de ejecución es más simple y eficiente incluso cuando el número de e/S y CPU son en su mayoría de la misma.