Моя система выполняет довольно тяжелую обработку, и я атакую производительность, чтобы дать мне возможность запускать больше тестовых прогонов в короткие сроки.Работа с проблемами производительности UDF - Ручное кэширование
У меня довольно много случаев, когда UDF должен быть вызван, скажем, 5 миллионов строк (и я довольно много думал, что вокруг этого не было).
Ну, оказывается, есть способ обойти его, и он дает большие улучшения производительности, когда UDF вызываются над набором различных параметров, несколько меньших, чем общий набор строк.
Рассмотрим UDF, который принимает набор входов и возвращает результат на основе сложной логики, но для набора входов на 5 м строк имеется всего 100 000 различных входов, скажем, и поэтому он будет производить только 100 000 различных результатов кортежи (мои конкретные случаи варьируются от процентных ставок до сложных присвоений кода, но все они дискретны - основной момент в этом методе состоит в том, что вы можете просто определить, будет ли трюк работать, запустив SELECT DISTINCT
).
я обнаружил, что делать что-то вроде этого:
INSERT INTO PreCalcs
SELECT param1
,param2
,dbo.udf_result(param1, param2) AS result
FROM (
SELECT DISTINCT param1, param2 FROM big_table
)
Когда PreCalcs соответствующим образом проиндексированы, сочетание этого с:
SELECT big_table.param1
,big_table.param2
,PreCalcs.result
FROM big_table
INNER JOIN PreCalcs
ON PreCalcs.param1 = big_table.param1
AND PreCalcs.param2 = big_table.param2
Вы получаете огромный прирост в производительности. По-видимому, только потому, что что-то детерминировано, это не значит, что SQL Server кэширует прошлые вызовы и повторно использует их, как можно подумать.
Единственное, что вы должны следить за то, где NULL разрешены, то вам нужно исправить ваш присоединяется осторожно:
SELECT big_table.param1
,big_table.param2
,PreCalcs.result
FROM big_table
INNER JOIN PreCalcs
ON (
PreCalcs.param1 = big_table.param1
OR COALESCE(PreCalcs.param1, big_table.param1) IS NULL
)
AND (
PreCalcs.param2 = big_table.param2
OR COALESCE(PreCalcs.param2, big_table.param2) IS NULL
)
Надежда это помогает и любые подобные трюки с UDF, или рефакторинга запросов для производительность приветствуется.
Я думаю, вопрос в том, почему такое кеширование вручную, как это необходимо - разве это не значит, что точка сервера знает, что функция детерминирована? И если это имеет большое значение, и если UDF настолько дороги, почему оптимизатор не делает это в плане выполнения?
Что вы хотите сказать? –
Я догадываюсь, вопрос в том, почему такое кеширование вручную, как это необходимо - разве это не значит, что точка сервера знает, что функция детерминирована? И если это имеет большое значение, и если UDF настолько дороги, почему оптимизатор не делает это в плане выполнения. –