1. 程式人生 > >巧用top percent優化top 1

巧用top percent優化top 1

比例 spa like 重排序 數據 per 表數據 多行 一個

廢話不多說,直接上sql

SELECT  top 1  B.CREW_ID, E.CREW_NAME,C.OFFBLK,C.ONBLK,dbo.PEK_OPS_Date(A.STD) as STD
          FROM dbo.FLIGHTS A 
        LEFT OUTER JOIN
          (SELECT DISTINCT TASK_ID, CREW_ID
           FROM dbo.CREW_TASK
          ) B ON A.COCKPIT_CREW_GROUP = B.TASK_ID 
        LEFT OUTER
JOIN dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID LEFT JOIN CREW_INFO E ON B.CREW_ID = E.CREW_ID LEFT JOIN FLIGHTS_STC F ON A.STC = F.IATA_CODE WHERE (A.COCKPIT_CREW_GROUP > 0) AND (A.STATUS=ATA) AND F.RATIO = 1 AND NOT (A.AC LIKE %--%) AND B.CREW_ID =
ISNULL(60, B.CREW_ID) AND C.OFFBLK is not null AND C.ONBLK is not null AND C.CREW_LEFT is not null AND C.CREW_RIGHT is not null ORDER BY A.STD desc

執行計劃如下:

技術分享圖片

執行時間:技術分享圖片 16秒、

分析:

嵌套循環之前,進行了排序操作,驅動表CREW_TASK 單表數據量300232。去重排序之後29w+。FLIGHTS 表單表44w+,這裏不走hash 的原因是因為top1導致。故去掉 TOP 1 限制語句

SELECT   B.CREW_ID, E.CREW_NAME,C.OFFBLK,C.ONBLK,dbo.PEK_OPS_Date(A.STD) as STD
          FROM dbo.FLIGHTS A 
        LEFT OUTER JOIN
          (SELECT DISTINCT TASK_ID, CREW_ID
           FROM dbo.CREW_TASK
          ) B ON A.COCKPIT_CREW_GROUP = B.TASK_ID 
        LEFT OUTER JOIN dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID 
        LEFT JOIN CREW_INFO E ON B.CREW_ID = E.CREW_ID
        LEFT JOIN FLIGHTS_STC F ON A.STC = F.IATA_CODE
      WHERE (A.COCKPIT_CREW_GROUP > 0) AND (A.STATUS=ATA)
        AND F.RATIO = 1 AND NOT (A.AC LIKE %--%)
        AND B.CREW_ID = ISNULL(60, B.CREW_ID) AND C.OFFBLK is not null AND C.ONBLK is not null
        AND  C.CREW_LEFT is not null AND C.CREW_RIGHT is not null 
     ORDER BY A.STD desc

執行計劃:

技術分享圖片

執行時間:技術分享圖片

分析:很明顯hash走了hash 匹配,可見在雙大表情況下,hash 匹配返回5000多行比嵌套循環返回一條要快得多。

方向明確,那麽怎麽取上述第一條數據呢?這個時候用到 TOP percent,也就是返回結果集的一個比例值,而不是 top 1 第一條數據:

sql如下:

SELECT  top 100 percent B.CREW_ID, E.CREW_NAME,C.OFFBLK,C.ONBLK,dbo.PEK_OPS_Date(A.STD) as STD
          FROM dbo.FLIGHTS A 
        LEFT OUTER JOIN
          (SELECT DISTINCT TASK_ID, CREW_ID
           FROM dbo.CREW_TASK
          ) B ON A.COCKPIT_CREW_GROUP = B.TASK_ID 
        LEFT OUTER JOIN dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID 
        LEFT JOIN CREW_INFO E ON B.CREW_ID = E.CREW_ID
        LEFT JOIN FLIGHTS_STC F ON A.STC = F.IATA_CODE
      WHERE (A.COCKPIT_CREW_GROUP > 0) AND (A.STATUS=ATA)
        AND F.RATIO = 1 AND NOT (A.AC LIKE %--%)
        AND B.CREW_ID = ISNULL(60, B.CREW_ID) AND C.OFFBLK is not null AND C.ONBLK is not null
        AND  C.CREW_LEFT is not null AND C.CREW_RIGHT is not null 
     ORDER BY A.STD desc

執行時間 技術分享圖片,返回100%的結果集

怎麽返回第一條?很簡單,我返回1%的結果集如下:

SELECT  top 1 percent B.CREW_ID, E.CREW_NAME,C.OFFBLK,C.ONBLK,dbo.PEK_OPS_Date(A.STD) as STD
          FROM dbo.FLIGHTS A 
        LEFT OUTER JOIN
          (SELECT DISTINCT TASK_ID, CREW_ID
           FROM dbo.CREW_TASK
          ) B ON A.COCKPIT_CREW_GROUP = B.TASK_ID 
        LEFT OUTER JOIN dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID 
        LEFT JOIN CREW_INFO E ON B.CREW_ID = E.CREW_ID
        LEFT JOIN FLIGHTS_STC F ON A.STC = F.IATA_CODE
      WHERE (A.COCKPIT_CREW_GROUP > 0) AND (A.STATUS=ATA)
        AND F.RATIO = 1 AND NOT (A.AC LIKE %--%)
        AND B.CREW_ID = ISNULL(60, B.CREW_ID) AND C.OFFBLK is not null AND C.ONBLK is not null
        AND  C.CREW_LEFT is not null AND C.CREW_RIGHT is not null 
     ORDER BY A.STD desc

執行時間:技術分享圖片,很明顯返回的是1%的結果集

返回0.01的結果集:

SELECT  top 0.01 percent B.CREW_ID, E.CREW_NAME,C.OFFBLK,C.ONBLK,dbo.PEK_OPS_Date(A.STD) as STD
          FROM dbo.FLIGHTS A 
        LEFT OUTER JOIN
          (SELECT DISTINCT TASK_ID, CREW_ID
           FROM dbo.CREW_TASK
          ) B ON A.COCKPIT_CREW_GROUP = B.TASK_ID 
        LEFT OUTER JOIN dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID 
        LEFT JOIN CREW_INFO E ON B.CREW_ID = E.CREW_ID
        LEFT JOIN FLIGHTS_STC F ON A.STC = F.IATA_CODE
      WHERE (A.COCKPIT_CREW_GROUP > 0) AND (A.STATUS=ATA)
        AND F.RATIO = 1 AND NOT (A.AC LIKE %--%)
        AND B.CREW_ID = ISNULL(60, B.CREW_ID) AND C.OFFBLK is not null AND C.ONBLK is not null
        AND  C.CREW_LEFT is not null AND C.CREW_RIGHT is not null 
     ORDER BY A.STD desc

執行時間:技術分享圖片 已經達到要求。

註意:這裏返回的是結果集的 百分比,雖然現在滿足取第一條的要求,但是是隨數據量增大,可能會多條, 故,外面包一層,取TOP 1 這樣能保證只取一條。

select top 1 AA.* from (
SELECT  top 1 percent B.CREW_ID, E.CREW_NAME,C.OFFBLK,C.ONBLK,dbo.PEK_OPS_Date(A.STD) as STD
          FROM dbo.FLIGHTS A 
        LEFT OUTER JOIN
          (SELECT DISTINCT TASK_ID, CREW_ID
           FROM dbo.CREW_TASK
          ) B ON A.COCKPIT_CREW_GROUP = B.TASK_ID 
        LEFT OUTER JOIN dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID 
        LEFT JOIN CREW_INFO E ON B.CREW_ID = E.CREW_ID
        LEFT JOIN FLIGHTS_STC F ON A.STC = F.IATA_CODE
      WHERE (A.COCKPIT_CREW_GROUP > 0) AND (A.STATUS=ATA)
        AND F.RATIO = 1 AND NOT (A.AC LIKE %--%)
        AND B.CREW_ID = ISNULL(60, B.CREW_ID) AND C.OFFBLK is not null AND C.ONBLK is not null
        AND  C.CREW_LEFT is not null AND C.CREW_RIGHT is not null 
     ORDER BY A.STD desc )AA

執行時間:技術分享圖片

收工!

巧用top percent優化top 1