Использование MSSQL 2005
Сегодня я играл с Scalar UDF в операторе where, чтобы увидеть некоторые затраты, связанные с выполнением вызовов и разницей в Io и т. Д.
I'mначиная с 2 основных таблиц.Клиент, который имеет 1 миллион строк.и покупки, которые имеют 100 000.Оба имеют столбец автоматической идентификации в качестве первичного ключа.Другие индексы не определены.
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
SET STATISTICS IO ON
SELECT * FROM Customer C
INNER JOIN Purchases P on C.[IDENTITY] = P.CustomerID
WHERE P.Amount > 1000
SET STATISTICS IO OFF
Возвращает статистику ввода-вывода
Table 'Customer'. Scan count 0, logical reads 3295, physical reads 1, read-ahead reads 32, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Purchases'. Scan count 1, logical reads 373, physical reads 1, read-ahead reads 370, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Так что просто чтобы увидеть влияние скалярного UDF, я просто переместил P.Amount> 1000 вUDF.Функция выглядит следующим образом:
CREATE FUNCTION [dbo].[HighValuePurchase]
(
@value int
)
RETURNS bit
AS
BEGIN
DECLARE @highValue bit
SET @highValue = '0'
IF @value > 1000
BEGIN
SET @highValue = '1'
END
RETURN @highValue
END
Итак, я запустил следующий запрос:
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
SET STATISTICS IO ON
SELECT * FROM Customer C
INNER JOIN Purchases P on C.[IDENTITY] = P.CustomerID
WHERE dbo.HighValuePurchase(P.Amount) = '1'
SET STATISTICS IO OFF
Я ожидал, что это будет работать хуже.Этот запрос вернул следующую статистику ввода-вывода:
Table 'Purchases'. Scan count 1, logical reads 373, physical reads 1, read-ahead reads 370, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customer'. Scan count 1, logical reads 35, physical reads 3, read-ahead reads 472, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Это также вернулось быстрее, чем запрос> 1000.В то время как были возвращены те же строки, порядок сортировки вызывающей UDF строки автоматически сортировался по C. [IDENTITY], где другой запрос оказался несортированным.Вероятно, это связано с тем, как комбинаты были выполнены в планах выполнения.Схема планов приведена ниже.
План выполнения для не-UDF показывает сканирование кластерного индекса для покупок и поиск кластерного индекса для клиентов, объединенных во вложенном соединении.
План выполнения для UDFВерсия показывает сканирование кластерного индекса для покупок, затем фильтр, затем сортировка.На клиенте есть кластерное сканирование индекса.Затем результаты объединяются в объединение слиянием.
Я уверен, что это связано с отсутствием индексов и т. Д., Но я не уверен, почему эти результаты такие, какие есть.Я чувствовал, что UDF работает мучительно медленно, и все говорят, что их использование - это, как правило, плохая идея, поэтому я провел этот тест вместе.Я не могу сейчас объяснить, почему версия UDF кажется намного лучше.