Исследуя комментарий Мэтта, я пересмотрел свое первоначальное утверждение. Он прав, будет разница в производительности между встроенной табличной функцией (ITVF) и многозначной табличной функцией (MSTVF), даже если они оба просто выполняют оператор SELECT. SQL Server будет воспринимать ITVF примерно как VIEW
в том смысле, что он будет рассчитывать план выполнения, используя последние статистические данные по рассматриваемым таблицам. MSTVF эквивалентно вставке всего содержимого вашего оператора SELECT в табличную переменную и последующему присоединению к ней. Таким образом, компилятор не может использовать какую-либо статистику таблиц для таблиц в MSTVF. Таким образом, при прочих равных условиях (что они редко бывают), ITVF будет работать лучше, чем MSTVF. В моих тестах разница в производительности во время выполнения была незначительной, однако с точки зрения статистики это было заметно.
В вашем случае две функции не являются функционально эквивалентными. Функция MSTV выполняет дополнительный запрос при каждом вызове и, что наиболее важно, фильтрует идентификатор клиента. В большом запросе оптимизатор не сможет воспользоваться преимуществами других типов объединений, так как ему потребуется вызывать функцию для каждого переданного customerId. Однако, если вы переписали свою функцию MSTV следующим образом:
CREATE FUNCTION MyNS.GetLastShipped()
RETURNS @CustomerOrder TABLE
(
SaleOrderID INT NOT NULL,
CustomerID INT NOT NULL,
OrderDate DATETIME NOT NULL,
OrderQty INT NOT NULL
)
AS
BEGIN
INSERT @CustomerOrder
SELECT a.SalesOrderID, a.CustomerID, a.OrderDate, b.OrderQty
FROM Sales.SalesOrderHeader a
INNER JOIN Sales.SalesOrderHeader b
ON a.SalesOrderID = b.SalesOrderID
INNER JOIN Production.Product c
ON b.ProductID = c.ProductID
WHERE a.OrderDate = (
Select Max(SH1.OrderDate)
FROM Sales.SalesOrderHeader As SH1
WHERE SH1.CustomerID = A.CustomerId
)
RETURN
END
GO
В запросе оптимизатор сможет вызвать эту функцию один раз и построить лучший план выполнения, но он все равно будет не лучше, чем эквивалентный непараметризированный ITVS или VIEW
.
ITVF должны быть предпочтительнее, чем MSTVF, когда это возможно, потому что типы данных, обнуляемость и параметры сортировки из столбцов в таблице, тогда как вы объявляете эти свойства в табличной функции с несколькими выражениями и, что важно, вы получите лучшие планы выполнения из ITVF. По моему опыту, я не нашел много обстоятельств, когда ITVF был лучшим вариантом, чем VIEW, но пробег может отличаться.
Благодаря Мэтту.
Сложение
С тех пор, как я недавно это выяснил, Уэйн Шеффилд сделал отличный анализ, сравнивающий разницу в производительности между функциями со встроенными таблицами и функциями с несколькими утверждениями.
Его оригинальный пост в блоге.
Копирование на SQL Server Central