2013-11-09 6 views
3

Хотя это довольно субъективный вопрос, но я считаю необходимым поделиться этим форумом.Почему SQL-функции быстрее, чем UDF

Я лично испытал это, когда создаю UDF (даже если это не сложно) и использовать его в моем SQL, он резко снижает производительность. Но когда я использую SQL inbuild function, они работают довольно быстро. Ярким примером этого является преобразование, логическое &.

Итак, мой вопрос: «Почему SQL в функциях сборки быстрее, чем UDF»? и было бы преимуществом, если бы кто-то мог направить меня, как я могу судить/манипулировать стоимостью функции либо математически, либо логически.

+0

Что вы подразумеваете под «пользовательской функцией»? Вы имеете в виду функции, созданные с помощью 'CREATE FUNCTION', или функции, написанные на C или C++ и включаемые динамически или во время компиляции? –

+1

Многие встроенные функции реализованы как специальные операторы в плане запроса (например, стандартные агрегаторы или функции окна) или достаточно просты, что в любом случае они не будут медленными. – siride

ответ

3

Это хорошо известная проблема со скалярными UDF в SQL Server.

Они не привязаны к плану, и их наложение увеличивает накладные расходы по сравнению с тем же логическим встроенным.

Следующая занимает менее 2 секунд на моей машине

WITH T10(N) AS 
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
) --10 rows          
, T(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
      FROM T10 a, T10 b, T10 c, T10 d, T10 e, T10 f, T10 g) -- 10 million rows 
SELECT MAX(N - N) 
FROM T 
OPTION (MAXDOP 1) 

Создание простой скалярную UDF

CREATE FUNCTION dbo.F1 (@N BIGINT) 
RETURNS BIGINT 
WITH SCHEMABINDING 
AS 
BEGIN 
RETURN (@N - @N) 
END 

И изменяя запрос MAX(dbo.F1(N)) вместо MAX(N - N) она занимает около 26 секунд с STATISTICS TIME OFF и 37 с ним.

Среднее увеличение 2,6 мкс/3,7 мкс для каждого из 10 миллионов вызовов функций.

Запуск профилировщика Visual Studio показывает, что подавляющее большинство времени взято под UDFInvoke. Имена методов в стеке вызовов дают некоторое представление о том, что делают дополнительные накладные расходы (копирование параметров, выполнение операторов, настройка контекста безопасности).

enter image description here

Перемещение логики в инлайн таблицы значной функции

CREATE FUNCTION dbo.F2 (@N BIGINT) 
RETURNS TABLE 
RETURN(SELECT @N - @N AS X) 

И переписав запрос как

SELECT MAX(X) 
FROM Nums 
CROSS APPLY dbo.F2(N) 

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

Смежные вопросы