Большая разница в производительности (от 1 часа до 1 минуты) обнаружена в SQL.Можете ли вы объяснить, почему?

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

Вопрос

Следующие запросы занимают 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 секунд.

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top