zoukankan      html  css  js  c++  java
  • sqlserver sql优化案例及思路

    始sql:

    SELECT TOP 100 PERCENT ZZ.CREW_NAME AS 机组, ZZ.CREW_ID, AA.年度时间, 
          CC.当月时间, DD.连续七天时间 AS 最近七天
    FROM (SELECT *
            FROM CABIN_CREW_INFO
            WHERE QUIT_DATE > CONVERT(VARCHAR, YEAR(43381)) + '-01-01') 
          ZZ LEFT OUTER JOIN
              (SELECT CREW_ID, DBO.HOURFORMAT(SUM(FLIGHT_TIME) / 60.0, 4) 
                   AS 年度时间
             FROM (SELECT A.FLTID AS FLTID, dbo.TOTTime2(C.OFFBLK, A.ETD, A.ATD, A.ATA, A.ETA,
          C.ONBLK, A.STATUS,D.QAR_OUT,D.QAR_OFF,D.QAR_ON,D.QAR_IN) AS FLIGHT_TIME, B.*
                     FROM dbo.FLY A LEFT OUTER JOIN
                               (SELECT DISTINCT TASK_ID, CREW_ID, ALLPOS
                              FROM dbo.CABIN_CREW_TASK_COPOS) B ON 
                           A.CABIN_CREW_GROUP = B.TASK_ID LEFT OUTER JOIN
                           dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID LEFT OUTER JOIN
                           dbo.FLIGHTS_QAR D ON A.FLTID = D.FLTID
                     WHERE (A.STC <> 'K') AND (A.STATUS <> 'CNL') AND 
                           (A.CABIN_CREW_GROUP > 0) AND (A.ATD BETWEEN 
                           CONVERT(VARCHAR, CONVERT(DATETIME, CONVERT(VARCHAR, 
                           YEAR(43381)) + '-1-1') - 3.0 / 24, 120) AND CONVERT(VARCHAR, 
                           CONVERT(DATETIME, (FLOOR(CONVERT(FLOAT, 43381)) + 1) 
                           - 3.0 / 24 - 1.0 / (24 * 60 * 60)), 120)) AND
                               ((SELECT COUNT(*)
                               FROM CABIN_SPECIAL_FLIGHTS
                               WHERE (CREW_ID = B.CREW_ID) AND (FLTID = A.FLTID)) = 0)) 
                   DEL
             GROUP BY CREW_ID) AA ON ZZ.CREW_ID = AA.CREW_ID LEFT OUTER JOIN
              (SELECT CREW_ID, DBO.HOURFORMAT(SUM(FLIGHT_TIME) / 60.0, 4) 
                   AS 当月时间
             FROM (SELECT A.FLTID AS FLTID, dbo.TOTTime2(C.OFFBLK, A.ETD, A.ATD, A.ATA, A.ETA,
          C.ONBLK, A.STATUS,D.QAR_OUT,D.QAR_OFF,D.QAR_ON,D.QAR_IN) AS FLIGHT_TIME, B.*
                     FROM dbo.FLIGHTS A LEFT OUTER JOIN
                               (SELECT DISTINCT TASK_ID, CREW_ID, ALLPOS
                              FROM dbo.CABIN_CREW_TASK_COPOS) B ON 
                           A.CABIN_CREW_GROUP = B.TASK_ID LEFT OUTER JOIN
                           dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID LEFT OUTER JOIN
                           dbo.FLIGHTS_QAR D ON A.FLTID = D.FLTID
                     WHERE (A.STC <> 'K') AND (A.STATUS <> 'CNL') AND 
                           (A.CABIN_CREW_GROUP > 0) AND (A.ATD BETWEEN 
                           CONVERT(VARCHAR, CONVERT(DATETIME, CONVERT(VARCHAR, 
                           YEAR(43381)) + '-' + CONVERT(VARCHAR, MONTH(43381)) + '-1') 
                           - 3.0 / 24, 120) AND CONVERT(VARCHAR, CONVERT(DATETIME, 
                           (FLOOR(CONVERT(FLOAT, 43381)) + 1) 
                           - 3.0 / 24 - 1.0 / (24 * 60 * 60)), 120)) AND
                               ((SELECT COUNT(*)
                               FROM CABIN_SPECIAL_FLIGHTS
                               WHERE (CREW_ID = B.CREW_ID) AND (FLTID = A.FLTID)) = 0)) 
                   DEL
             GROUP BY CREW_ID) CC ON ZZ.CREW_ID = CC.CREW_ID LEFT OUTER JOIN
              (SELECT CREW_ID, DBO.HOURFORMAT(SUM(FLIGHT_TIME) / 60.0, 4) 
                   AS 连续七天时间
             FROM (SELECT A.FLTID AS FLTID, dbo.TOTTime2(C.OFFBLK, A.ETD, A.ATD, A.ATA, A.ETA,
          C.ONBLK, A.STATUS,D.QAR_OUT,D.QAR_OFF,D.QAR_ON,D.QAR_IN) AS FLIGHT_TIME, B.*
                     FROM dbo.FLIGHTS A LEFT OUTER JOIN
                               (SELECT DISTINCT TASK_ID, CREW_ID, ALLPOS
                              FROM dbo.CABIN_CREW_TASK_COPOS) B ON
                           A.CABIN_CREW_GROUP = B.TASK_ID LEFT OUTER JOIN
                           dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID LEFT OUTER JOIN
                           dbo.FLIGHTS_QAR D ON A.FLTID = D.FLTID
                     WHERE (A.STC <> 'K') AND (A.STATUS <> 'CNL') AND 
                           (A.CABIN_CREW_GROUP > 0) AND (A.ATD BETWEEN 
                           CONVERT(VARCHAR, CONVERT(DATETIME, CONVERT(VARCHAR, 
                           YEAR(DATEADD(DD, - 6, 43381))) + '-' + CONVERT(VARCHAR, 
                           MONTH(DATEADD(DD, - 6, 43381))) + '-' + CONVERT(VARCHAR, 
                           DAY(DATEADD(DD, - 6, 43381)))) - 3.0 / 24, 120) AND 
                           CONVERT(VARCHAR, CONVERT(DATETIME, (FLOOR(CONVERT(FLOAT, 
                           43381)) + 1) - 3.0 / 24 - 1.0 / (24 * 60 * 60)), 120)) AND
                               ((SELECT COUNT(*)
                               FROM CABIN_SPECIAL_FLIGHTS
                               WHERE (CREW_ID = B.CREW_ID) AND (FLTID = A.FLTID)) = 0)) 
                   DEL
             GROUP BY CREW_ID) DD ON ZZ.CREW_ID = DD.CREW_ID
    ORDER BY DD.连续七天时间 DESC
    

     

       优化思路

             1:分析最慢点:

            

    -----分解sql执行,问题出现在这个sql
    SELECT CREW_ID, DBO.HOURFORMAT(SUM(FLIGHT_TIME) / 60.0, 4) 
                   AS 年度时间
             FROM (SELECT A.FLTID AS FLTID, dbo.TOTTime2(C.OFFBLK, A.ETD, A.ATD, A.ATA, A.ETA,
          C.ONBLK, A.STATUS,D.QAR_OUT,D.QAR_OFF,D.QAR_ON,D.QAR_IN) AS FLIGHT_TIME, B.*
                     FROM dbo.fly A LEFT OUTER JOIN
                               (SELECT DISTINCT TASK_ID, CREW_ID, ALLPOS
                              FROM dbo.CABIN_CREW_TASK_COPOS) B ON 
                           A.CABIN_CREW_GROUP = B.TASK_ID LEFT OUTER JOIN
                           dbo.fly_CREW_REPORT C ON A.FLTID = C.FLTID LEFT OUTER JOIN
                           dbo.fly_QAR D ON A.FLTID = D.FLTID
                     WHERE (A.STC <> 'K') AND (A.STATUS <> 'CNL') AND 
                           (A.CABIN_CREW_GROUP > 0) AND (A.ATD BETWEEN 
                           CONVERT(VARCHAR, CONVERT(DATETIME, CONVERT(VARCHAR, 
                           YEAR(43381)) + '-1-1') - 3.0 / 24, 120) AND CONVERT(VARCHAR, 
                           CONVERT(DATETIME, (FLOOR(CONVERT(FLOAT, 43381)) + 1) 
                           - 3.0 / 24 - 1.0 / (24 * 60 * 60)), 120)) AND
                               ((SELECT COUNT(*)
                               FROM CABIN_SPECIAL_fly
                               WHERE (CREW_ID = B.CREW_ID) AND (FLTID = A.FLTID)) = 0)) 
                   DEL
             GROUP BY CREW_ID
    

      

              2:根据sqlserver提示建立索引,未达到效果。

    ------tunning1
    -USE [ISA]
    GO
    CREATE NONCLUSTERED INDEX [<Missing_INDEX_20181009]
    ON [dbo].[fly] ([STATUS],[ATD],[STC],[CABIN_CREW_GROUP])
    INCLUDE ([FLTID],[ETD],[ETA],[ATA])
    GO
    

      

    3:红色部分大部分重复,出去一个and 条件谓词都一样,这种sql难以迭代更新维护,考虑with as 语句改写
    with SS as 
    (SELECT A.FLTID AS FLTID,A.ATD AS ATD ,dbo.TOTTime2(C.OFFBLK, A.ETD, A.ATD, A.ATA, A.ETA,
          C.ONBLK, A.STATUS,D.QAR_OUT,D.QAR_OFF,D.QAR_ON,D.QAR_IN) AS FLIGHT_TIME, B.*
                     FROM dbo.FLIGHTS A LEFT OUTER JOIN
                               (SELECT DISTINCT TASK_ID, CREW_ID, ALLPOS FROM dbo.CABIN_CREW_TASK_COPOS) B ON 
                               A.CABIN_CREW_GROUP = B.TASK_ID LEFT OUTER JOIN
                               dbo.FLIGHTS_CREW_REPORT C ON A.FLTID = C.FLTID LEFT OUTER JOIN
                               dbo.FLIGHTS_QAR D ON A.FLTID = D.FLTID					   
                     WHERE (A.STC <> 'K') AND (A.STATUS <> 'CNL') AND (A.CABIN_CREW_GROUP > 0) AND ((SELECT COUNT(*) 
    				 FROM CABIN_SPECIAL_FLIGHTS WHERE (CREW_ID = B.CREW_ID) AND (FLTID = A.FLTID)) = 0))
    SELECT TOP 100 PERCENT ZZ.CREW_NAME AS 机组, ZZ.CREW_ID, AA.年度时间, 
          CC.当月时间, DD.连续七天时间 AS 最近七天
    FROM (SELECT *
            FROM CABIN_CREW_INFO
            WHERE QUIT_DATE > CONVERT(VARCHAR, YEAR(43381)) + '-01-01') 
          ZZ LEFT OUTER JOIN
              (SELECT CREW_ID, DBO.HOURFORMAT(SUM(FLIGHT_TIME) / 60.0, 4) 
                   AS 年度时间
             FROM ( SELECT * FROM SS WHERE (ATD BETWEEN 
                           CONVERT(VARCHAR, CONVERT(DATETIME, CONVERT(VARCHAR, 
                           YEAR(43381)) + '-1-1') - 3.0 / 24, 120) AND CONVERT(VARCHAR, 
                           CONVERT(DATETIME, (FLOOR(CONVERT(FLOAT, 43381)) + 1) 
                           - 3.0 / 24 - 1.0 / (24 * 60 * 60)), 120))
    						   ) 
                   DEL
             GROUP BY CREW_ID) AA ON ZZ.CREW_ID = AA.CREW_ID LEFT OUTER JOIN
              (SELECT CREW_ID, DBO.HOURFORMAT(SUM(FLIGHT_TIME) / 60.0, 4) 
                   AS 当月时间
             FROM (SELECT * FROM SS WHERE (ATD BETWEEN 
                           CONVERT(VARCHAR, CONVERT(DATETIME, CONVERT(VARCHAR, 
                           YEAR(43381)) + '-' + CONVERT(VARCHAR, MONTH(43381)) + '-1') 
                           - 3.0 / 24, 120) AND CONVERT(VARCHAR, CONVERT(DATETIME, 
                           (FLOOR(CONVERT(FLOAT, 43381)) + 1) 
                           - 3.0 / 24 - 1.0 / (24 * 60 * 60)), 120)) 
    					   ) 
                   DEL
             GROUP BY CREW_ID) CC ON ZZ.CREW_ID = CC.CREW_ID LEFT OUTER JOIN
              (SELECT CREW_ID, DBO.HOURFORMAT(SUM(FLIGHT_TIME) / 60.0, 4) 
                   AS 连续七天时间
             FROM (SELECT * FROM SS WHERE  
    					   (ATD BETWEEN 
                           CONVERT(VARCHAR, CONVERT(DATETIME, CONVERT(VARCHAR, 
                           YEAR(DATEADD(DD, - 6, 43381))) + '-' + CONVERT(VARCHAR, 
                           MONTH(DATEADD(DD, - 6, 43381))) + '-' + CONVERT(VARCHAR, 
                           DAY(DATEADD(DD, - 6, 43381)))) - 3.0 / 24, 120) AND 
                           CONVERT(VARCHAR, CONVERT(DATETIME, (FLOOR(CONVERT(FLOAT, 
                           43381)) + 1) - 3.0 / 24 - 1.0 / (24 * 60 * 60)), 120))
    					   ) 
                   DEL
             GROUP BY CREW_ID) DD ON ZZ.CREW_ID = DD.CREW_ID
    ORDER BY DD.连续七天时间 DESC
    

      

    改写之后,sql临时表逻辑清晰,易于维护和性能优化,临时表SS,只是条件不同。在oracle这样能大幅度减少临时表扫描次数,可惜在sqlserver 效果不明显。
    4:终极杀手锏,分析执行计划

    
    

    查看上述sql红框sql进行了全表扫描及排序,可以考虑合适的索引替代:

    create index CABIN_CREW_TASK_COPOS_20181009 on CABIN_CREW_TASK_COPOS(TASK_ID) INCLUDE(CREW_ID,ALLPOS)
    

      

    立即可以看到优化效果

    SQL Server 执行时间:

    CPU 时间 = 25859 毫秒,占用时间 = 29679 毫秒。

    总结:拿到sql,首先看整体框架,然后进行慢sql 分解,然后进行分布优化。通常情况下都是索引缺缺失,在OLTP环境中添加索引dba 需要权衡。

    
    
     
  • 相关阅读:
    跟随标准与Webkit源码探究DOM -- 获取元素之querySelector,querySelectorAll
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByClassName
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByTagName
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByName
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementById
    原生DOM探究 -- NodeList v.s. HTMLCollection
    Jira 在流程节点中每个状态权限设置
    Eureka集群配置
    Linux下搭建 redis
    python框架django中结合vue进行前后端分离
  • 原文地址:https://www.cnblogs.com/monkeybron/p/9760929.html
Copyright © 2011-2022 走看看