Большая разница в производительности (от 1 часа до 1 минуты) обнаружена в SQL. Вы можете объяснить, почему? - PullRequest
0 голосов
/ 30 ноября 2009

Следующие запросы занимают 70 минут и 1 минуту соответственно на стандартной машине для 1 миллиона записей. Какие могут быть возможные причины?

Запрос [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

Модифицированный запрос [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

[Модифицированный]

Я попытался воссоздать сценарий с похожей функцией, чтобы увидеть, оцениваются ли параметры для каждой строки.

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

Но я получаю то же значение для столбца «Параметр» для миллиона записей, обработанных за 38 секунд.

Ответы [ 2 ]

6 голосов
/ 30 ноября 2009

В вашем первом запросе ваши fn_cdc_increment_lsn и fn_cdc_get_min_lsn выполняются для каждой строки. Во втором примере только один раз.

2 голосов
/ 30 ноября 2009

Даже детерминированные скалярные функции оцениваются как минимум один раз в строке. Если одна и та же детерминированная скалярная функция встречается несколько раз в одной и той же «строке» с одинаковыми параметрами, я полагаю, что только тогда она будет оценена один раз, например в CASE WHEN fn_X(a, b, c) > 0 THEN fn_X(a, b, c) ELSE 0 END или что-то в этом роде.

Я думаю, что ваша проблема RAND в том, что вы продолжаете перезаряжать:

Повторные вызовы RAND () с то же самое начальное значение возвращает то же самое Результаты.

Для одного соединения, если RAND () вызывается с указанным начальным значением, все последующие вызовы RAND () производят результаты на основе посеянного RAND () вызов. Например, следующий запрос всегда будет возвращать одну и ту же последовательность чисел.

Я занялся кэшированием результатов скалярных функций, как вы указали, - даже зашел до того, что предварительно вычислил таблицы результатов скалярных функций и присоединился к ним. Что-то должно быть сделано в конце концов, чтобы скалярные функции выполнялись. Правильно нет, лучшим вариантом является CLR - очевидно, они намного превосходят UDF-функции SQL. К сожалению, я не могу использовать их в моей текущей среде.

...