Я исследую проблему со скоростью выполнения встроенной табличной функции в SQL Server. Или я подумал, что проблема в этом. Я сталкивался с
Код T-SQL очень медленный при сохранении в виде встроенной табличной функции
, которая выглядела многообещающе, поскольку описывала то, что я видел, ноУ меня, казалось, была противоположная проблема - когда я передавал переменные в свою функцию, это занимало 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 использовать эффективный?
PS вот код внутреннего вызова 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
)