Grande diferença de desempenho (1 hora a 1 minuto) encontrada no SQL.Você pode explicar por quê?

StackOverflow https://stackoverflow.com/questions/1819513

Pergunta

As consultas a seguir levam 70 minutos e 1 minuto, respectivamente, em uma máquina padrão para 1 milhão de registros.Quais poderiam ser as possíveis razões?

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]

Tentei recriar o cenário com uma função semelhante para ver se os parâmetros são avaliados para cada linha.

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())))

Mas estou obtendo o mesmo valor para a coluna 'Parâmetro' para um milhão de registros processados ​​em 38 segundos.

Foi útil?

Solução

Mesmo funções escalares determinísticas são avaliadas pelo menos uma vez por linha.Se a mesma função escalar determinística ocorrer várias vezes na mesma "linha" com os mesmos parâmetros, acredito que somente então ela será avaliada uma vez - por exemplo.em um CASE WHEN fn_X(a, b, c) > 0 THEN fn_X(a, b, c) ELSE 0 END ou algo assim.

Acho que o seu problema RAND é porque você continua propagando novamente:

Chamadas repetitivas de rand () com o mesmo valor de semente retornam os mesmos resultados.

Para uma conexão, se Rand () for chamado com um valor de semente especificado, todas as chamadas subsequentes de rand () produzirão resultados com base na chamada de rand () semeada.Por exemplo, a consulta a seguir sempre retornará a mesma sequência de números.

Comecei a armazenar em cache os resultados da função escalar, como você indicou - chegando ao ponto de pré-calcular tabelas de resultados da função escalar e juntá-las a elas.Eventualmente, algo precisa ser feito para que as funções escalares funcionem.Certo, não, a melhor opção é o CLR - aparentemente, eles superam em muito os UDFs SQL.Infelizmente, não posso usá-los em meu ambiente atual.

Outras dicas

Na sua primeira consulta, seu fn_cdc_increment_lsn e fn_cdc_get_min_lsn é executado para cada linha.No segundo exemplo, apenas uma vez.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top