为什么此TSQL子查询会减慢此查询的速度

时间:2013-06-10 16:35:43

标签: performance tsql subquery

我有一个查询,我需要加快速度:

    SELECT
Distinct Refs.SpecialtyReferredTo
FROM ABI_RiO.dbo.vwSGReferrals Refs
LEFT JOIN ABI_RiO.dbo.vwSGAppointmentsPD Apps ON Refs.ClientID = Apps. ClientID AND Refs.ReferralNumber = Apps.ReferralNumber
LEFT OUTER JOIN ABI_RiO.SchemaSG.AmsOutcome AS AOUT ON AOUT.Code=APPs.Outcome
LEFT JOIN ABI_RiO.SchemaSG.ClientIndex CI ON Refs.ClientID = CI.ClientID
LEFT JOIN ABI_RiO.SchemaSG.GenGPPractice GP ON GP.Code = CI.AIMTCCurrentGPPractice
where Refs.DischargeReason IS NULL
AND ((Apps.ContactID = ISNULL((SELECT Max(Apps2.ContactID)
FROM ABI_RiO.dbo.vwSGReferrals Refs2
LEFT JOIN ABI_RiO.dbo.vwSGAppointmentsPD Apps2 ON Refs2.ClientID = Apps2. ClientID AND Refs2.ReferralNumber = Apps2.ReferralNumber
LEFT OUTER JOIN ABI_RiO.SchemaSG.AmsOutcome AS AOUT ON AOUT.Code=APPs2.Outcome
WHERE Refs2.ClientID = Refs.ClientID
AND Refs2.ReferralNumber = Refs.ReferralNumber
AND NationalCode=5),
(SELECT Max(Apps2.ContactID)
FROM ABI_RiO.dbo.vwSGReferrals Refs2
LEFT JOIN ABI_RiO.dbo.vwSGAppointmentsPD Apps2 ON Refs2.ClientID = Apps2. ClientID AND Refs2.ReferralNumber = Apps2.ReferralNumber
WHERE Refs2.ClientID = Refs.ClientID
AND Refs2.ReferralNumber = Refs.ReferralNumber
))) OR Apps.ContactID IS NULL)
GROUP BY GP.Code, Refs.SpecialtyReferredTo

这需要永远执行。但是,如果我拆分查询的最后一部分,代码会在几秒钟内执行。即。

     SELECT
Distinct GP.Code, Refs.SpecialtyReferredTo
FROM ABI_RiO.dbo.vwSGReferrals Refs
LEFT JOIN ABI_RiO.dbo.vwSGAppointmentsPD Apps ON Refs.ClientID = Apps. ClientID AND Refs.ReferralNumber = Apps.ReferralNumber
LEFT OUTER JOIN ABI_RiO.SchemaSG.AmsOutcome AS AOUT ON AOUT.Code=APPs.Outcome
LEFT JOIN ABI_RiO.SchemaSG.ClientIndex CI ON Refs.ClientID = CI.ClientID
LEFT JOIN ABI_RiO.SchemaSG.GenGPPractice GP ON GP.Code = CI.AIMTCCurrentGPPractice
where Refs.DischargeReason IS NULL
AND ((Apps.ContactID = ((SELECT Max(Apps2.ContactID)
FROM ABI_RiO.dbo.vwSGReferrals Refs2
LEFT JOIN ABI_RiO.dbo.vwSGAppointmentsPD Apps2 ON Refs2.ClientID = Apps2. ClientID AND Refs2.ReferralNumber = Apps2.ReferralNumber
LEFT OUTER JOIN ABI_RiO.SchemaSG.AmsOutcome AS AOUT ON AOUT.Code=APPs2.Outcome
WHERE Refs2.ClientID = Refs.ClientID
AND Refs2.ReferralNumber = Refs.ReferralNumber
AND NationalCode=5))))
GROUP BY GP.Code, Refs.SpecialtyReferredTo
ORDER BY GP.Code

这意味着我的问题在于查询的最后部分:

 (SELECT Max(Apps2.ContactID)
FROM ABI_RiO.dbo.vwSGReferrals Refs2
LEFT JOIN ABI_RiO.dbo.vwSGAppointmentsPD Apps2 ON Refs2.ClientID = Apps2. ClientID AND Refs2.ReferralNumber = Apps2.ReferralNumber
WHERE Refs2.ClientID = Refs.ClientID
AND Refs2.ReferralNumber = Refs.ReferralNumber
))) OR Apps.ContactID IS NULL)
--GROUP BY GP.Code, Refs.SpecialtyReferredTo
--ORDER BY GP.Code

将最后一个查询块添加回来会导致最终输出的数据扩展约10%。

任何人都可以帮我重写这个查询并解释为什么最后一部分会导致执行性能下降。 欢呼声。

[R

1 个答案:

答案 0 :(得分:0)

我在这里的第一个倾向是将您的ISNULL部分中的相关子查询更改为两个获得这些值的外部应用计算。

    SELECT
DISTINCT    Refs.SpecialtyReferredTo
    FROM    ABI_RiO.dbo.vwSGReferrals Refs
    LEFT JOIN ABI_RiO.dbo.vwSGAppointmentsPD Apps
    ON      Refs.ClientID = Apps.ClientID
            AND Refs.ReferralNumber = Apps.ReferralNumber
    LEFT OUTER JOIN ABI_RiO.SchemaSG.AmsOutcome AS AOUT
    ON      AOUT.Code = APPs.Outcome
    LEFT JOIN ABI_RiO.SchemaSG.ClientIndex CI
    ON      Refs.ClientID = CI.ClientID
    LEFT JOIN ABI_RiO.SchemaSG.GenGPPractice GP
    ON      GP.Code = CI.AIMTCCurrentGPPractice
OUTER APPLY (select max(Apps2.ContactID) as ContactID1 ...) as OuterApply1
OUTER APPLY (select max(Apps2.ContactID) as ContactID2 ...) as OuterApply2
    WHERE   Refs.DischargeReason IS NULL
AND (Apps.ContactID = ISNULL(ContactID1, ContactID2) or Apps.ContactID IS NULL )

一般来说,相关的子查询会导致性能问题,因为您正在尝试计算每一行的问题。将这些计算切换为OUTER APPLY至少可以让您将它们作为一组进行处理。

这里有一些外部申请的例子:http://www.mssqltips.com/sqlservertip/1958/sql-server-cross-apply-and-outer-apply/ 在这里:https://www.simple-talk.com/sql/t-sql-programming/sql-server-apply-basics/