Добавление критериев в процедуру приводит к снижению производительности
У меня есть функция fncDeptInfo. В настоящее время он возвращает около 1000 записей менее чем за секунду:
ALTER FUNCTION [dbo].[fncDeptInfo]()
RETURNS TABLE
AS
RETURN
(
SELECT
tblContacts.Contact,
CASE tblContacts.Parent1
WHEN 1900 THEN 0
WHEN 1901 THEN 1
WHEN 1902 THEN 2
WHEN 1903 THEN 3
WHEN 1904 THEN 4
WHEN 1905 THEN 5
WHEN 1906 THEN 6
ELSE NULL
END AS PRArea,
DISTRICT.Contact AS DistrictID
FROM
tblContacts
LEFT OUTER JOIN
tblContacts AS DISTRICT ON tblContacts.Parent2 = DISTRICT.Contact
WHERE
(tblContacts.ContactType = 'Fire') AND
(tblContacts.SubType = 'Dept')
)
У меня есть процедура, которая вызывает эту функцию ниже:
SELECT
fncDeptInfo.Contact, DEPTPAID.CurPaid,
fncDeptInfo.PRArea, fncDeptInfo.DistrictID
FROM
fncDeptInfo() AS fncDeptInfo
INNER JOIN
(SELECT
v_Item.BillToContact AS Contact,
SUM(CASE WHEN Expiration = @Date1 AND tblProgramCodes.FormatCode = 'Membership' THEN 1 ELSE 0 END) AS CurPaid
FROM
v_Item
INNER JOIN
tblProgramCodes ON v_Item.ProgramCodeID = tblProgramCodes.ProgramCode
GROUP BY
v_Item.BillToContact) DEPTPAID ON fncDeptInfo.Contact = DEPTPAID.Contact
WHERE
(fncDeptInfo.PRArea > 0) AND (fncDeptInfo.DistrictID > 0)
ORDER BY
fncDeptInfo.Contact
v_Item
это очень сложное представление, которое объединяет финансовые записи в разных таблицах. Возвращает более 300 000 строк. Процедура, как задумано, возвращается через 5 секунд.
Если я добавлю этот фрагмент, чтобы получить информацию о Chief в fncDeptInfo, процедура займет полторы минуты. Но fncDeptInfo сам по себе возвращается примерно через секунду:
LEFT OUTER JOIN fncEmployee(GETDATE(), 'Chief') AS CHIEF
ON tblContacts.Contact = CHIEF.Contact2
Если я добавлю этот критерий к процедуре, то теперь это займет полторы минуты. Однако, если я удаляю fncDeptInfo из процедуры, он снова возвращается через 5 секунд:
WHERE CurPaid > 0
Я предполагаю, что представление как-то задействовано в обоих случаях и неоднократно вызывается. Может кто-нибудь предложить лучший способ сделать так, чтобы производительность не страдала?
1 ответ
Простым вариантом является выбор вашего представления во временную таблицу, что предотвращает повторный вызов представления. Что-то вроде
IF Object_ID ('tempdb..vitem_tmp') is not null DROP TABLE #vitem_tmp
SELECT *
INTO #vitem_tmp
FROM v_Item
[Your query, referencing #vitem_tmp instead of v_Item]