SQL Server:查询性能分析 - 任何优化想法?

时间:2013-10-02 16:18:16

标签: sql sql-server performance query-optimization sql-server-profiler

我已阅读多篇推荐使用SQL Server Profiler的文章,我也是。

我有一个非常重要的查询,它会使应用程序不时冻结。该查询包含多个LEFT JOIN ... ON ... AND (... AND ...) OR (... AND ...)

我对正在使用的关系模型没有权限,所以我必须使用它。

该询问是关于在发生火灾时附近的危险品附近,以帮助计划消防员干预计划。查询有效,只需要进行一些优化。

现在,我的此查询包含6635 Reads296 CPU0 Writes281 Duration

我能想到的只是查询太慢而且可能太重而服务器无法执行。换句话说,它根本不是最优的。

如果重要,因为我相信它,查询在其where子句中有多个计算,如:

ATN2(SQRT(SIN(RADIANS(@latitude - CASE WHEN LocationType = @locationType THEN Buildings.Latitude ELSE Intersections.Latitude END) / 2 *...

我没有预算购买工具或其他任何工具。

  

更新

根据要求,这是一个可怕的查询:

SELECT PHM.ID, HP.Name, PHMD.TL, PHMD.QTY
    , PHMD.CT, PHMD.C, PHMD.MU
    , HP.HR, HP.FR, HP.RR, HP.SR
    , PHMD.CP
    , A.HN, A.Alpha
    , CASE WHEN PHM.LT <> @7 THEN TL.D ELSE TL.D + ' ' + TL2.D END AS TLcol
    , C.D AS CD
FROM PHM 
    LEFT JOIN PHMD ON PHMD.ExID = PHM.ID 
    LEFT JOIN HP ON PHMD.HPID = HP.ID 
    LEFT JOIN BP ON PHM.LT=@5 
        AND BP.ID = PHM.BPID 
    LEFT JOIN A ON (PHM.LT=@4 
            AND A.ID = PHM.AID) 
        OR (PHM.LT=@5 
            AND BP.AID = A.ID) 
    LEFT JOIN I ON I.ID = PHM.IID  
    LEFT JOIN TL ON (PHM.LT<>@7 
            AND A.TLID = TL.ID) 
        OR (PHM.LT=@7 
            AND I.TLID1 = TL.ID)  
    LEFT JOIN TL AS TL2 ON PHM.LT=@7 
        AND I.TLID2 = TL2.ID 
    LEFT JOIN C ON TL.CID=C.ID 
    LEFT JOIN B ON A.ID = B.ExID 
    LEFT JOIN B ON B.ID = B.BID 
WHERE EXISTS (SELECT * FROM PHMD WHERE PHMD.ExID=PHM.ID)
    AND (((PHM.LT=@4 AND PHM.AID=@8)    
        OR (PHM.LT=@5 AND PHM.BPID IN (SELECT ID FROM BP WHERE AID=@8)) 
    OR (PHM.LT=@6 AND PHM.BID IN (SELECT BID FROM B WHERE ExID=@8))) 
     AND PHM.DV = (
            SELECT MAX(PHMLD.DV) 
                FROM PHM AS PHMLD 
                WHERE PHMLD.LT = PHM.LT 
                    AND ISNULL(PHMLD.AddressID,0) = ISNULL(PHM.AID,0) 
                    AND ISNULL(PHMLD.SuiteID,0) = ISNULL(PHM.SID,0) 
                    AND ISNULL(PHMLD.BPID,0) = ISNULL(PHM.BPID,0) 
                    AND ISNULL(PHMLD.IID,0)=ISNULL(PHM.IID,0) 
                    AND ISNULL(PHMLD.BID,0)=ISNULL(PHM.BID,0)) 
                    OR 6371010 * (2 * ATN2(
                            SQRT((SIN(RADIANS(@1 - CASE WHEN PHM.LT<>@6 THEN B.LAT ELSE I.LAT END)/2) 
                                * SIN(RADIANS(@1 - CASE WHEN PHM.LT<>@6 THEN B.LAT ELSE I.LAT END)/2) 
                                + COS(RADIANS(CASE WHEN PHM.LT<>@6 THEN B.LAT ELSE I.LAT END)) 
                                * COS(RADIANS(@1)) 
                                * SIN(RADIANS(@2 - CASE WHEN PHM.LT<>@6 THEN B.LNG ELSE I.LNG END)/2) 
                                * SIN(RADIANS(@2 - CASE WHEN PHM.LT<>@6 THEN B.LNG ELSE I.LNG END)/2)))
                            , SQRT(1-(SIN(RADIANS(@1 - CASE WHEN PHM.LT<>@6 THEN B.LAT ELSE I.LAT END)/2) 
                                * SIN(RADIANS(@1 - CASE WHEN PHM.LT<>@6 THEN B.LAT ELSE I.LAT END)/2) 
                                + COS(RADIANS(CASE WHEN PHM.LT<>@6 THEN B.LAT ELSE I.LAT END)) 
                                * COS(RADIANS(@1)) 
                                * SIN(RADIANS(@2 - CASE WHEN PHM.LT<>@6 THEN B.LNG ELSE I.LNG END)/2) 
                                * SIN(RADIANS(@2 - CASE WHEN PHM.LT<>@6 THEN B.LNG ELSE I.LNG END)/2))))
                        ) <= @3)
  

SET SHOWPLAN_XML ON更新

请访问以下链接以了解执行showplan。 http://pastebin.com/k6GxxSKF

谢谢你的帮助! =)

1 个答案:

答案 0 :(得分:1)

查看查询执行计划我可以看到花费在LEFT OUTER联接上的时间最多。查询计划显示73%的查询时间/资源花费在该一个联接上。

你需要左外连接吗?

大多数查询都使用索引查找并返回非常少的行,这些行尽可能好。但是,他们使用NESTED LOOP连接,这不是最有效的JOIN类型。我怀疑如果您强制使用MERGE甚至HASH联接类型,您可能会看到不同的性能。有关如何强制使用其他类型的JOIN,请参阅this link。但这并不是真的值得推荐的。

这些表经常更新吗?还是他们非常静止?这些表中还有多少数据。我怀疑如果SQL服务器使用错误的JOIN类型,那么表上的统计信息可能已过期。尝试在表上运行UPDATE STATISTICS并检查查询计划是否更改。