为什么表值函数的性能优于select direct语句?

ron*_*ran 4 sql-server user-defined-functions inline-functions table-functions

一只忙碌的猫

我使用AdventureWorks2012进行测试.和我的问题:为什么SELECT语句直接性能低于表值函数.我只将SELECT statemnt放入表值函数和完全相反的性能.

CREATE FUNCTION [dbo].[atest1]
(
    @iBusinessEntityID  INT
)
RETURNS @t TABLE
(
    [BusinessEntityID]  INT
  , [NationalIDNumber]  NVARCHAR(15)
  , [JobTitle]          NVARCHAR(50)
)
AS
    BEGIN
        INSERT INTO @t
               SELECT 
                   [e].[BusinessEntityID]
                 , [e].[NationalIDNumber]
                 , [e].[JobTitle]
               FROM [HumanResources].[Employee] [e]
               INNER JOIN [Person].[Person] [p]
                    ON [p].[BusinessEntityID] = [e].[BusinessEntityID]
               WHERE [e].[BusinessEntityID] = @iBusinessEntityID;
        RETURN;
    END;

--TEST PERFORMANCE
SELECT 
    *
FROM [dbo].[atest1](5);
GO
SELECT 
    [e].[BusinessEntityID]
  , [e].[NationalIDNumber]
  , [e].[JobTitle]
FROM [HumanResources].[Employee] [e]
INNER JOIN [Person].[Person] [p]
     ON [p].[BusinessEntityID] = [e].[BusinessEntityID]
WHERE [e].[BusinessEntityID] = 5;
Run Code Online (Sandbox Code Playgroud)

sep*_*pic 7

这里的问题是,估计的计划SSMS往往显示错误的百分比,如果是,UDF它几乎总是错误的.

cost percentage是与其他操作相比的操作估计成本,但是如果UDF SSMS没有检查UDF的内部.

UDF在我的服务器上创建了你的文本a GUID,所以我可以很容易地返回这个UDF的计划:

CREATE FUNCTION [dbo].[atest1] (@iBusinessEntityID int)
RETURNS @t TABLE(BusinessEntityID int,NationalIDNumber nvarchar(15),JobTitle nvarchar(50)) AS
BEGIN
INSERT INTO @t /*3C6A985B-748B-44D4-9F76-1A0866342728*/ -- HERE IS MY GUID
SELECT e.BusinessEntityID, e.NationalIDNumber, e.JobTitle
FROM HumanResources.Employee e INNER JOIN Person.Person p ON p.BusinessEntityID = e.BusinessEntityID
WHERE e.BusinessEntityID = @iBusinessEntityID
RETURN
END
Run Code Online (Sandbox Code Playgroud)

现在我执行此函数并以这种方式检索其计划:

select p.query_plan
from sys.dm_exec_cached_plans cp
     cross apply sys.dm_exec_sql_text(cp.plan_handle) t
     cross apply sys.dm_exec_query_plan(cp.plan_handle) p
where cp.objtype = 'Proc'
      and t.text like '%3C6A985B-748B-44D4-9F76-1A0866342728%'
Run Code Online (Sandbox Code Playgroud)

我检查了这个计划,它正好是你的"直接声明"的计划.它的SELECT部分是相同的,但是INSERT在表格中还有一个变量scan在主计划中.因此,您可以清楚地看到您的UDF成本不能低,它等于"直接声明"成本加INSERT成本加表变量scan成本.

在此输入图像描述

在这种情况下,表很小,只有一个UDF调用,所以你不能注意执行时间的差异,但如果你做一个循环执行你的"直接语句"更多次并调用UDF更多次你可能会看到执行时间差异,"直接声明"将更快.但无论如何SSMS都会坚持UDF降低成本.