Question

I have read multiple articles that recommends using SQL Server Profiler, so did I.

I have a quite important query which makes the application freeze from time to time. The query includes multiple LEFT JOIN ... ON ... AND (... AND ...) OR (... AND ...).

I have no authority on the relational model that is being used, so I must work with it.

The query is about getting nearby hazardous products places in case of fire in order to help plan the fire fighters intervention plan. The query works, it only need some optimizations.

Now, I have this query had 6635 Reads, 296 CPU, 0 Writes, 281 Duration.

All I can come up with is that the query is too slow and probably too heavy for the server to perform. In other words, it's not optimal at all.

In case it matters, because I believe it does, the query has multiple calculations in its where clause like:

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

I have no budget to buy tools or whatsoever.

UPDATE

As per request, here's the monstrous query:

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 UPDATE

Please visit the following link for the execution showplan. http://pastebin.com/k6GxxSKF

Thanks for you kind help! =)

Was it helpful?

Solution

Looking at query execution plan I can see that the most time is spent on the LEFT OUTER join.The query plan shows 73% of the query time/resources is spent on that one join.

Do you need the left outer join?

Most of the query is using index seeks and return very little rows which is as good as it gets. However they are using NESTED LOOP joins which is not the most efficient JOIN type. I suspect if you forced the use of the MERGE or even HASH join types you might see different performance. See this link on how to force another type of JOIN. This is not really recommended though.

Are these tables frequently updated? Or are they very static? Also how much data are in these tables. I suspect that if SQL server is using the wrong JOIN type it might be that the statistics on the tables are out of date. Try running a UPDATE STATISTICS on the tables and check if the query plan changes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top