Gran diferencia de rendimiento (1 hora a 1 minuto) encontrada en SQL. ¿Puedes explicar porque?
-
10-07-2019 - |
Pregunta
Las siguientes consultas toman 70 minutos y 1 minuto respectivamente en una máquina estándar para 1 millón de registros. ¿Cuáles podrían ser las posibles razones?
Consulta [01:10:00]
SELECT *
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
ELSE sys.fn_cdc_increment_lsn(0x00) END
, sys.fn_cdc_get_max_lsn()
, 'all with mask')
WHERE __$operation <> 1
Consulta modificada [00:01:10]
DECLARE @MinLSN binary(10)
DECLARE @MaxLSN binary(10)
SELECT @MaxLSN= sys.fn_cdc_get_max_lsn()
SELECT @MinLSN=CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
ELSE sys.fn_cdc_increment_lsn(0x00) END
SELECT *
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
@MinLSN, @MaxLSN, 'all with mask') WHERE __$operation <> 1
[Modificado]
Traté de recrear el escenario con una función similar para ver si los parámetros se evalúan para cada fila.
CREATE FUNCTION Fn_Test(@a decimal)RETURNS TABLE
AS
RETURN
(
SELECT @a Parameter, Getdate() Dt, PartitionTest.*
FROM PartitionTest
);
SELECT * FROM Fn_Test(RAND(DATEPART(s,GETDATE())))
Pero obtengo el mismo valor para la columna 'Parámetro' para un millón de registros procesados ??en 38 segundos.
Solución
Incluso las funciones escalares deterministas se evalúan al menos una vez por fila. Si la misma función escalar determinista se produce varias veces en la misma '' fila '' con los mismos parámetros, creo que solo entonces se evaluará una vez, p. en un CASO CUANDO fn_X (a, b, c) > 0 ENTONCES fn_X (a, b, c) ELSE 0 END
o algo así.
Creo que su problema RAND se debe a que continúa reiniciando:
Llamadas repetitivas de RAND () con el el mismo valor inicial devuelve el mismo resultados.
Para una conexión, si RAND () es llamado con un valor semilla especificado, todas las llamadas posteriores de RAND () producen resultados basados ??en la RAND sembrada () llamada. Por ejemplo, la siguiente consulta siempre devolverá la misma secuencia de números.
He empezado a almacenar en caché los resultados de la función escalar como usted ha indicado, incluso yendo tan lejos como para precalcular tablas de resultados de la función escalar y unirme a ellas. Eventualmente, se debe hacer algo para que las funciones escalares funcionen. Correcto, la mejor opción es el CLR, aparentemente estos superan con creces las UDF de SQL. Lamentablemente, no puedo usarlos en mi entorno actual.
Otros consejos
En su primera consulta, su fn_cdc_increment_lsn
y fn_cdc_get_min_lsn
se ejecutan para cada fila. En el segundo ejemplo, solo una vez.