В выходные я обновил SQL Server 2000 до 2008. Теперь один запрос выполняется очень медленно (> 30 секунд для примерно 50 строк).
Запрос:
SELECT TOP 200 AccData.SurName + ', ' + AccData.FirstNames AS Name,
DATEDIFF(day, COALESCE (AccData.DateReceived, AccData.DateOpened,
AccData.InjuryDate),
GETDATE()) AS Duration, AccData.M46No, Clients.ClientName,
AccData.HomePhone, AccData.WorkPhone, AccData.InjuryDate,
AccData.ClaimID,
luClaimStatus.Meaning AS Status, AccData.Claim,
vw_LastMedCert.Fitness, vw_LastMedCert.UntilDate
FROM AccData INNER JOIN
Clients ON AccData.ClientID = Clients.ID
INNER JOIN
luClaimStatus ON AccData.ClaimStatus = luClaimStatus.ClaimStatus
LEFT OUTER JOIN
vw_LastMedCert ON AccData.Claim = vw_LastMedCert.Claim
WHERE AccData.ClientID>1 and CaseManagerId = :CaseManagerID
and (DateClosed is null or AccData.ClaimStatus ='R')
order by Surname, FirstNames
Проблема связана с LastMedCert
ALTER VIEW [dbo].[vw_LastMedCert] WITH SCHEMABINDING
AS
SELECT Claim, ClaimId, ReferralID, FromDate, UntilDate, Fitness, DateSeen,
DateEntered, PeriodFor
FROM dbo.Med_cert
WHERE (ReferralID IN
(SELECT MAX(ReferralID) AS MaxOfReferralID
FROM dbo.Med_cert AS Med_cert_1
WHERE (Fitness IS NOT NULL)
GROUP BY Claim))
Есть идеи? Я перестроил индексы и обновил статистику
План выполнения:
|--Compute Scalar(DEFINE:([Expr1020]=datediff(day,[Expr1024],getdate())))
|--Nested Loops(Left Outer Join, OUTER REFERENCES:([CmsDB].[dbo].[AccData].[Claim]))
|--Nested Loops(Inner Join, OUTER REFERENCES:([CmsDB].[dbo].[AccData].[ClientID]))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([CmsDB].[dbo].[AccData].[ClaimStatus]))
| | |--Compute Scalar(DEFINE:([Expr1019]=((([CmsDB].[dbo].[AccData].[SurName]+', ')+[CmsDB].[dbo].[AccData].[FirstNames])+' ')+CASE WHEN [CmsDB].[dbo].[AccData].[MiddleNames] IS NOT NULL THEN [CmsDB].[dbo].[AccData].[MiddleNames] ELSE '' END, [Expr1024]=CASE WHEN [CmsDB].[dbo].[AccData].[DateReceived] IS NOT NULL THEN [CmsDB].[dbo].[AccData].[DateReceived] ELSE CASE WHEN [CmsDB].[dbo].[AccData].[DateOpened] IS NOT NULL THEN [CmsDB].[dbo].[AccData].[DateOpened] ELSE [CmsDB].[dbo].[AccData].[InjuryDate] END END))
| | | |--Nested Loops(Inner Join, OUTER REFERENCES:([Uniq1002], [CmsDB].[dbo].[AccData].[Claim], [CmsDB].[dbo].[AccData].[SurName], [CmsDB].[dbo].[AccData].[FirstNames], [Expr1027]) WITH ORDERED PREFETCH)
| | | |--Index Seek(OBJECT:([CmsDB].[dbo].[AccData].[IX_AccData_ByCaseManagerId]), SEEK:([CmsDB].[dbo].[AccData].[CaseManagerID]=(100346)) ORDERED FORWARD)
| | | |--Clustered Index Seek(OBJECT:([CmsDB].[dbo].[AccData].[byName]), SEEK:([CmsDB].[dbo].[AccData].[SurName]=[CmsDB].[dbo].[AccData].[SurName] AND [CmsDB].[dbo].[AccData].[FirstNames]=[CmsDB].[dbo].[AccData].[FirstNames] AND [CmsDB].[dbo].[AccData].[Claim]=[CmsDB].[dbo].[AccData].[Claim] AND [Uniq1002]=[Uniq1002]), WHERE:([CmsDB].[dbo].[AccData].[ClientID]>(1) AND ([CmsDB].[dbo].[AccData].[DateClosed] IS NULL OR [CmsDB].[dbo].[AccData].[ClaimStatus]='R')) LOOKUP ORDERED FORWARD)
| | |--Clustered Index Seek(OBJECT:([CmsDB].[dbo].[luClaimStatus].[PK_luClaimStatus_1__172]), SEEK:([CmsDB].[dbo].[luClaimStatus].[ClaimStatus]=[CmsDB].[dbo].[AccData].[ClaimStatus]) ORDERED FORWARD)
| |--Index Seek(OBJECT:([CmsDB].[dbo].[Clients].[PK_Clients_2__13]), SEEK:([CmsDB].[dbo].[Clients].[ID]=[CmsDB].[dbo].[AccData].[ClientID]), WHERE:([CmsDB].[dbo].[Clients].[ID]>(1)) ORDERED FORWARD)
|--Nested Loops(Inner Join, WHERE:([Expr1018]=[CmsDB].[dbo].[Med_cert].[ReferralID]))
|--Clustered Index Seek(OBJECT:([CmsDB].[dbo].[Med_cert].[byClaim]), SEEK:([CmsDB].[dbo].[Med_cert].[Claim]=[CmsDB].[dbo].[AccData].[Claim]) ORDERED FORWARD)
|--Table Spool
|--Stream Aggregate(GROUP BY:([CmsDB].[dbo].[Med_cert].[Claim]) DEFINE:([Expr1018]=MAX([CmsDB].[dbo].[Med_cert].[ReferralID])))
|--Clustered Index Scan(OBJECT:([CmsDB].[dbo].[Med_cert].[byClaim]), WHERE:([CmsDB].[dbo].[Med_cert].[Fitness] IS NOT NULL) ORDERED FORWARD)
Я решил решение, переписав начальный запрос. Теперь он запускается примерно через 1 секунду, но я все еще хочу знать, что пошло не так, чтобы я мог исправить это, если он появится снова.
Резюме
Начальное время выполнения запроса составляло около 2 минут в зависимости от параметров. Добавление индексов в соответствии с предложением плана выполнения и dm_db_missing_index_details сократило время выполнения до 4 секунд
Добавление хэш-подсказки уменьшило время выполнения до 2 секунд.
Это был сложный вопрос, решить, какой из ответов принять, большинство ответов оказали некоторую помощь.