И ничего о функциях. Почему информация о функции отсутствует в фактическом плане?
Это сделано из соображений производительности.
Функции, которые содержат BEGIN
и END
в определении создают новый фрейм стека T-SQL для каждой входной строки. Другими словами, тело функции выполняется отдельно для каждой строки ввода . Этот факт объясняет большинство проблем с производительностью, связанных со скалярными и многооператорными функциями T-SQL (обратите внимание, что встроенные табличные функции не используют BEGIN...END
синтаксис).
В контексте вашего вопроса это приведет к полному SHOWPLAN
выводу для каждой строки. Вывод XML-плана довольно многословен и дорог в производстве, поэтому создание полного вывода для каждой строки было бы плохой идеей в общих чертах.
пример
Рассмотрим ниже скалярную функцию T-SQL, созданную в образце базы данных AdventureWorks , которая возвращает имя продукта по его идентификатору:
CREATE FUNCTION dbo.DumbNameLookup
(
@ProductID integer
)
RETURNS dbo.Name
AS
BEGIN
RETURN
(
SELECT
p.Name
FROM Production.Product AS p
WHERE
p.ProductID = @ProductID
);
END;
План предварительного исполнения
План предварительного выполнения (примерный план в SSMS) показывает информацию о плане для родительского оператора и вызовов вложенных функций:
-- Pre-execution plan shows main query and nested function call
SET SHOWPLAN_XML ON;
GO
SELECT dbo.DumbNameLookup(1);
GO
SET SHOWPLAN_XML OFF;
Выход SSMS:
Тот же XML, который просматривается в SQL Sentry Plan Explorer, более четко показывает вложенную природу вызовов:
Вывод после выполнения
SSMS показывает подробности только для основного запроса, когда запрашивается вывод плана после выполнения:
-- Post-execution plan shows main query only
SET STATISTICS XML ON;
SELECT dbo.DumbNameLookup(1);
SET STATISTICS XML OFF;
Влияние производительности на выполнение других действий можно продемонстрировать с помощью класса событий XML-профиля Showplan в SQL Server Profiler, используя запрос, который вызывает функцию несколько раз (один раз для каждой входной строки):
SELECT TOP (5)
p.ProductID,
dbo.DumbNameLookup(p.ProductID)
FROM Production.Product AS p;
Профилировщик вывода:
Существует пять отдельных планов после выполнения для выполнения функций и один для родительского запроса. Пять функциональных планов выглядят так на нижней панели профилировщика:
Родительский план запроса:
Выполнение запроса без TOP (5)
предложения приводит к полному плану выполнения для каждой из 504 строк в таблице Product. Вы можете, вероятно, увидеть, как это быстро выйдет из-под контроля с большими столами.
Ситуация для триггеров обратная. Они не показывают никакой информации о плане до выполнения, но включают план после выполнения. Это отражает основанную на множестве природу триггеров; каждый запускается один раз для всех затронутых строк, а не один раз для каждой строки.