SQL Server执行速度根据向内联表函数提供参数的方式而有很大不同

问题描述 投票:0回答:1

我正在研究SQL Server中内联表函数的执行速度问题。或那是我以为问题所在。我碰到

T-SQL code is extremely slow when saved as an Inline Table-valued Function

看起来很有希望,因为它描述了我所看到的,但是我似乎遇到了相反的问题-当我将变量传递给函数时,花了17秒,但是当我在查询窗口中运行函数的代码时,对变量使用DECLARE语句(我认为有效地使它们成为文字),运行时间以毫秒为单位。相同的代码,相同的参数-只是将它们包装在一个内联表函数中似乎就将其向下拖动。

我试图将查询减少到仍然表现出该行为的最小可能代码。我正在使用许多现有的内联表函数(所有这些都工作了好几年),并且设法将我的代码简化为只需要调用一个现有的内联表函数即可突出显示速度差异。但是这样做时,我注意到了一些很奇怪的东西

SELECT strStudentNumber
FROM dbo.udfNominalSnapshot('2019', 'REG')

需要17秒,而

DECLARE @strAcademicSessionStart varchar(4) = '2019'
DECLARE  @strProgressCode varchar(12)= 'REG'

SELECT strStudentNumber
FROM dbo.udfNominalSnapshot(@strAcademicSessionStart, @strProgressCode)

需要毫秒!因此,与将代码包装到内联表函数中无关,而与将参数传递到其中的嵌套函数有关。根据引用的文章,我猜想有两种不同的执行计划在起作用,但是我不知道为什么/如何做,更重要的是,我可以说服SQL Server使用高效的方法吗?

P.S。这是响应注释请求的内部UDF调用的代码]

ALTER FUNCTION [dbo].[udfNominalSnapshot] 
(   
    @strAcademicSessionStart varchar(4)='%',
        @strProgressCode varchar(10)='%'
)
RETURNS TABLE 
AS
RETURN 
(
SELECT     TOP 100 PERCENT S.strStudentNumber, S.strSurname, S.strForenames, S.strTitle, S.strPreviousSurname, S.dtmDoB, S.strGender, S.strMaritalStatus, 
                      S.strResidencyCode, S.strNationalityCode, S.strHESAnumber, S.strSLCnumber, S.strPreviousSchoolName, S.strPreviousSchoolCode, 
                      S.strPreviousSchoolType, 
                      COLLEGE_EMAIL.strEmailAddress AS strEmailAlias, 
                      PERSONAL_EMAIL.strEmailAddress AS strPersonalEmail,
                      P.[str(Sub)Plan], P.intYearOfCourse, P.strProgressCode, 
                      P.strAcademicSessionStart, strC2Knumber AS C2K_ID, AcadPlan,  strC2KmailAlias
                      ,ISNULL([strC2KmailAlias], [strC2Knumber]) + '@c2kni.net' AS strC2KmailAddress

FROM         dbo.tblStudents AS S
                      LEFT JOIN
                      dbo.udfMostRecentEmail('COLLEGE') AS COLLEGE_EMAIL ON S.strStudentNumber = COLLEGE_EMAIL.strStudentNumber
                      LEFT JOIN
                      dbo.udfMostRecentEmail('PERSONAL') AS PERSONAL_EMAIL ON S.strStudentNumber = PERSONAL_EMAIL.strStudentNumber
                       INNER JOIN
                      dbo.udfProgressHistory(@strAcademicSessionStart) AS P ON S.strStudentNumber = P.strStudentNumber
WHERE     (P.strProgressCode LIKE @strProgressCode OR (SUBSTRING(@strProgressCode, 1, 1) = '^' AND P.strProgressCode NOT LIKE SUBSTRING(@strProgressCode, 2, LEN(@strProgressCode)))) AND 
(P.strStudentNumber NOT IN
                          (SELECT     strStudentNumber
                            FROM          dbo.tblPilgrims
                            WHERE      (strAcademicSessionStart = @strAcademicSessionStart) AND (strScheme = 'BEI')))
ORDER BY P.[str(Sub)Plan], P.intYearOfCourse, S.strSurname
)
sql-server sql-execution-plan
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.