最近我们将数据库从SQL Server 2005迁移到SQL Server 2012.从那时起,当我们使用以下查询时遇到性能问题:
SELECT
dbo.Candidates.CandidateID AS Candidates_CandidateID,
dbo.Candidates.DateCreated AS Candidates_DateCreated,
dbo.Candidates.Gender AS Candidates_Gender,
dbo.Titles.TitleName AS Titles_TitleName,
dbo.Addresses.CityName AS Addresses_CityName,
dbo.Countries.CountryName AS Candidates_CountryName,
dbo.Candidates.PhoneNumber AS Candidates_PhoneNumber,
dbo.Candidates.MobilePhoneNumber AS Candidates_MobilePhoneNumber,
dbo.Candidates.BirthDate AS Candidates_BirthDate,
dbo.vwConcatenatedBranchesPerCandidate.Branches_BrancheName,
dbo.States.StateName AS States_StateName,
dbo.SubStates.SubStateName AS SubStates_SubStateName,
dbo.Candidates.StateDate AS Candidates_StateDate,
dbo.Candidates.Nationality AS Candidates_Nationality,
dbo.Candidates.AvailableFromDate AS Candidates_AvailableFromDate,
dbo.Candidates.AvailableUntilDate AS Candidates_AvailableUntilDate,
dbo.Availabilities.AvailabilityName AS Availabilities_AvailabilityName,
dbo.AvailableDurations.AvailableDurationName AS AvailableDurations_AvailableDurationName,
dbo.Candidates.HoursPerWeekMin AS Candidates_HoursPerWeekMin,
dbo.Candidates.HoursPerWeekMax AS Candidates_HoursPerWeekMax,
dbo.vwCandidatesLastLetter.Candidates_DateLastLetter,
dbo.vwCandidatesLastEmail.Candidates_DateLastEmail,
dbo.Candidates.FirstName AS Candidates_FirstName,
dbo.Candidates.Initials AS Candidates_Initials,
dbo.Candidates.Infix AS Candidates_Infix,
dbo.Candidates.Surname AS Candidates_Surname,
dbo.vwConcatenatedEmailAddressesPerCandidate.Email AS EmailAddresses_EmailAddress,
dbo.vwConcatenatedCurrentFunctionNamesPerCandidate.Candidates_CurrentFunctionNames,
dbo.CandidateSources.SourceName AS CandidateSources_SourceName,
dbo.Candidates.CandidateSourceText AS Candidates_CandidateSourceText, CandidateIsActiveInAMatch.Candidates_ActiveInOtherMatch,
dbo.vwCandidatesUsersFullName.Candidates_FullUserName,
dbo.Candidates.Remark AS Candidates_Remark,
dbo.Candidates.HasWorkedForUs AS Candidates_HasWorkedForUs,
dbo.GenerateFullName(dbo.Candidates.Surname, dbo.Candidates.FirstName, dbo.Candidates.Initials, dbo.Candidates.Infix) AS Candidates_FullName,
dbo.vwCandidatesLastMarketingMail.Candidates_DateMarketingMail,
dbo.Addresses.StreetName AS Addresses_StreetName,
dbo.Addresses.PostalCode AS Addresses_PostalCode,
dbo.Candidates.AvailabilityNote,
dbo.Candidates.Greeting,
dbo.Candidates.StartDate AS Candidates_StartDate,
dbo.Candidates.EndDate AS Candidates_EndDate
FROM
dbo.vwCandidatesLastEmail RIGHT OUTER JOIN
dbo.CandidateSources RIGHT OUTER JOIN
dbo.Candidates LEFT OUTER JOIN
dbo.vwCandidatesLastMarketingMail ON dbo.Candidates.CandidateID = dbo.vwCandidatesLastMarketingMail.Candidates_CandidateID LEFT OUTER JOIN
dbo.Titles ON dbo.Candidates.TitleID = dbo.Titles.TitleID LEFT OUTER JOIN
dbo.vwCandidatesUsersFullName ON dbo.Candidates.CandidateID = dbo.vwCandidatesUsersFullName.Candidates_CandidateID LEFT OUTER JOIN
dbo.CandidateIsActiveInAMatch() AS CandidateIsActiveInAMatch ON dbo.Candidates.CandidateID = CandidateIsActiveInAMatch.CandidateID ON
dbo.CandidateSources.CandidatesSourceID = dbo.Candidates.CandidateSourceID LEFT OUTER JOIN
dbo.vwConcatenatedCurrentFunctionNamesPerCandidate ON
dbo.Candidates.CandidateID = dbo.vwConcatenatedCurrentFunctionNamesPerCandidate.CandidateID LEFT OUTER JOIN
dbo.vwConcatenatedEmailAddressesPerCandidate ON dbo.Candidates.CandidateID = dbo.vwConcatenatedEmailAddressesPerCandidate.CandidateID LEFT OUTER JOIN
dbo.AvailableDurations ON dbo.Candidates.AvailableDurationID = dbo.AvailableDurations.AvailableDurationID LEFT OUTER JOIN
dbo.Availabilities ON dbo.Candidates.AvailabilityID = dbo.Availabilities.AvailabilityID LEFT OUTER JOIN
dbo.vwConcatenatedBranchesPerCandidate ON dbo.Candidates.CandidateID = dbo.vwConcatenatedBranchesPerCandidate.CandidateID LEFT OUTER JOIN
dbo.States ON dbo.Candidates.StateID = dbo.States.StateID LEFT OUTER JOIN
dbo.SubStates ON dbo.Candidates.SubStateID = dbo.SubStates.SubStateID AND dbo.States.StateID = dbo.SubStates.StateID ON
dbo.vwCandidatesLastEmail.Candidates_CandidateID = dbo.Candidates.CandidateID LEFT OUTER JOIN
dbo.vwCandidatesLastLetter ON dbo.Candidates.CandidateID = dbo.vwCandidatesLastLetter.Candidates_CandidateID LEFT OUTER JOIN
dbo.Countries INNER JOIN
dbo.Addresses ON dbo.Countries.CountryID = dbo.Addresses.CountryID ON dbo.Candidates.AddressID = dbo.Addresses.AddressID
查询使用一些使用自定义用户定义的聚合连接函数的子视图(视图以vwConcatenated开头...),一些子视图使用以下查询(它们都以LastEmail,LastLetter等结尾...):
SELECT
dbo.Candidates.CandidateID AS Candidates_CandidateID,
MAX(dbo.Actions.DateCreated) AS Candidates_DateLastEmail
FROM
dbo.Candidates
INNER JOIN
dbo.Actions_Candidates
ON
dbo.Candidates.CandidateID = dbo.Actions_Candidates.CandidateID
INNER JOIN
dbo.Actions
ON
dbo.Actions_Candidates.ActionID = dbo.Actions.ActionID
INNER JOIN
dbo.ActionTypes
ON
dbo.Actions.ActionTypeID = dbo.ActionTypes.ActionTypeID
WHERE
(dbo.ActionTypes.ActionTypeCodeInternal = N'CANDIDATE_EMAIL') OR
(dbo.ActionTypes.ActionTypeCodeInternal = N'SENT_EMAIL')
GROUP BY dbo.Candidates.CandidateID
在SQL Server 2012中,此查询会抛出一条警告,其中包含以下消息:操作员使用tempdb在溢出级别为1的执行期间溢出数据。
它看起来似乎没有缓存查询,因为当我第二次运行相同的查询时,它只需要上一次尝试。当我在SQL 2005中运行相同的查询两次,然后第二次在秒内返回。
为什么SQL Server 2012和2005处理查询的方式如此不同?为什么SQL 2012中的查询速度要慢得多?
执行计划的链接