En su pregunta, detalla algunas pruebas que ha preparado donde "prueba" que la opción de adición es más rápida que comparar las columnas discretas. Sospecho que su metodología de prueba puede ser defectuosa de varias maneras, como han aludido @gbn y @srutzky.
Primero, debe asegurarse de que no está probando SQL Server Management Studio (o cualquier cliente que esté usando). Por ejemplo, si está ejecutando un archivo SELECT *
desde una tabla con 3 millones de filas, está probando principalmente la capacidad de SSMS para extraer filas de SQL Server y representarlas en la pantalla. Es mucho mejor usar algo como lo SELECT COUNT(1)
que niega la necesidad de extraer millones de filas en la red y representarlas en la pantalla.
En segundo lugar, debe tener en cuenta la caché de datos de SQL Server. Por lo general, probamos la velocidad de leer datos del almacenamiento y procesarlos desde un caché en frío (es decir, los almacenamientos intermedios de SQL Server están vacíos). Ocasionalmente, tiene sentido hacer todas sus pruebas con un caché cálido, pero debe abordar sus pruebas explícitamente con eso en mente.
Para una prueba de memoria caché en frío, debe ejecutar CHECKPOINT
y DBCC DROPCLEANBUFFERS
antes de cada ejecución de la prueba.
Para la prueba que ha preguntado en su pregunta, creé el siguiente banco de pruebas:
IF COALESCE(OBJECT_ID('tempdb..#SomeTest'), 0) <> 0
BEGIN
DROP TABLE #SomeTest;
END
CREATE TABLE #SomeTest
(
TestID INT NOT NULL
PRIMARY KEY
IDENTITY(1,1)
, A INT NOT NULL
, B FLOAT NOT NULL
, C MONEY NOT NULL
, D BIGINT NOT NULL
);
INSERT INTO #SomeTest (A, B, C, D)
SELECT o1.object_id, o2.object_id, o3.object_id, o4.object_id
FROM sys.objects o1
, sys.objects o2
, sys.objects o3
, sys.objects o4;
SELECT COUNT(1)
FROM #SomeTest;
Esto devuelve un recuento de 260,144,641 en mi máquina.
Para probar el método de "adición", ejecuto:
CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE (st.A + st.B + st.C + st.D) = 0;
GO
SET STATISTICS IO, TIME OFF;
La pestaña de mensajes muestra:
Tabla '#SomeTest'. Cuenta de escaneo 3, lecturas lógicas 1322661, lecturas físicas 0, lecturas anticipadas 1313877, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas anticipadas lob 0.
Tiempos de ejecución de SQL Server: tiempo de CPU = 49047 ms, tiempo transcurrido = 173451 ms.
Para la prueba de "columnas discretas":
CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE st.A = 0
AND st.B = 0
AND st.C = 0
AND st.D = 0;
GO
SET STATISTICS IO, TIME OFF;
nuevamente, desde la pestaña de mensajes:
Tabla '#SomeTest'. Cuenta de escaneo 3, lecturas lógicas 1322661, lecturas físicas 0, lecturas anticipadas 1322661, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas anticipadas lob 0.
Tiempos de ejecución de SQL Server: tiempo de CPU = 8938 ms, tiempo transcurrido = 162581 ms.
De las estadísticas anteriores, puede ver la segunda variante, con las columnas discretas en comparación con 0, el tiempo transcurrido es aproximadamente 10 segundos más corto y el tiempo de CPU es aproximadamente 6 veces menor. Las largas duraciones en mis pruebas anteriores son principalmente el resultado de leer muchas filas del disco. Si baja el número de filas a 3 millones, verá que las proporciones siguen siendo las mismas, pero los tiempos transcurridos disminuyen notablemente, ya que la E / S del disco tiene un efecto mucho menor.
Con el método "Adición":
Tabla '#SomeTest'. Recuento de escaneo 3, lecturas lógicas 15255, lecturas físicas 0, lecturas anticipadas 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas anticipadas lob 0.
Tiempos de ejecución de SQL Server: tiempo de CPU = 499 ms, tiempo transcurrido = 256 ms.
Con el método de "columnas discretas":
Tabla '#SomeTest'. Recuento de escaneo 3, lecturas lógicas 15255, lecturas físicas 0, lecturas anticipadas 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas anticipadas lob 0.
Tiempos de ejecución de SQL Server: tiempo de CPU = 94 ms, tiempo transcurrido = 53 ms.
¿Qué marcará una gran diferencia para esta prueba? Un índice apropiado, como:
CREATE INDEX IX_SomeTest ON #SomeTest(A, B, C, D);
El método de "suma":
Tabla '#SomeTest'. Cuenta de escaneo 3, lecturas lógicas 14235, lecturas físicas 0, lecturas de lectura anticipada 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas de lectura lob 0.
Tiempos de ejecución de SQL Server: tiempo de CPU = 546 ms, tiempo transcurrido = 314 ms.
El método de "columnas discretas":
Tabla '#SomeTest'. Cuenta de escaneo 1, lecturas lógicas 3, lecturas físicas 0, lecturas de lectura anticipada 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas de lectura lob 0.
Tiempos de ejecución de SQL Server: tiempo de CPU = 0 ms, tiempo transcurrido = 0 ms.
El plan de ejecución para cada consulta (con el índice anterior en el lugar) es bastante revelador.
El método de "adición", que debe realizar un análisis de todo el índice:
y el método de "columnas discretas", que puede buscar la primera fila del índice donde está la columna de índice inicial A
, es cero: