2

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

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

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

该查询是关于在发生火灾时获取附近的危险品场所,以帮助制定消防员干预计划。查询有效,它只需要一些优化。

现在,我有这个查询了6635 Reads, 296 CPU, 0 Writes, 281 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更新

请访问以下链接了解执行展示计划。 http://pastebin.com/k6GxxSKF

谢谢你的帮助!=)

4

1 回答 1

2

查看查询执行计划,我可以看到大部分时间都花在了连接上LEFT OUTER。查询计划显示 73% 的查询时间/资源都花在了那个连接上。

你需要左外连接吗?

大多数查询都使用索引查找并返回非常少的行,这与它获得的一样好。但是,他们使用的NESTED LOOP连接不是最有效的 JOIN 类型。我怀疑如果您强制使用MERGE甚至HASH连接类型,您可能会看到不同的性能。请参阅此链接以了解如何强制使用另一种类型的JOIN. 不过,这并不是真正推荐的。

这些表是否经常更新?还是它们非常静态?还有这些表中有多少数据。我怀疑如果 SQL Server 使用了错误的 JOIN 类型,则可能是表上的统计信息已过时。尝试UPDATE STATISTICS在表上运行 a 并检查查询计划是否更改。

于 2013-10-03T21:29:12.440 回答