如何优化我的SQL查询以更快地运行?

loo*_*evo 0 sql sql-server optimization lag

SELECT 
   b.User_Id
   ,(CONVERT(varchar, DATEADD(hh, - 7, b.callstartdt), 101))as 'Dt'
   ,(COUNT(distinct b.SeqNum ) + Count(distinct c.SeqNum) + count(distinct d.seqnum)) as 'TotalCalls'
   ,COUNT(distinct b.SeqNum )as 'ACD'
   ,COUNT(distinct c.SeqNum)as 'AOD'
   ,COUNT(distinct d.seqnum)  as 'Manual'
   ,COUNT(distinct e.SeqNum)as 'Contacts'
   ,COUNT (distinct es.seqnum) as 'Success'
FROM 
   [detail_epro].[dbo].[ACDCallDetail]as b 
LEFT JOIN 
   [detail_epro].[dbo].[AODCallDetail]as c on c.User_Id = b.User_Id   
LEFT JOIN
   [detail_epro].[dbo].[manualCallDetail]as d on d.User_Id = b.User_Id 
LEFT JOIN
   (SELECT 
       USER_ID, CallStartDt, SeqNum
    FROM 
       [detail_epro].[dbo].[AgentDispoDetail]
    WHERE 
        Disp_Id IN 
                (100000150, 100000126,  100000137,  100000093,  100000133,  
                100000123,  100000094,  100000161,  100000162,  100000085,  
                100000084,  100000086,  100000096,  100000087,  100000157,  
                100000088,  100000097,  100000154,  100000148,  100000134,  
                100000131,  100000160,  100000156,  100000165,  100000166,  
                100000122,  100000121,  100000138,  100000130,  100000144,  
                100000132,  100000158,  100000098,  100000147,  100000100,  
                100000153,  100000139,  100000145,  100000101,  100000140,  
                100000102,  100000103,  100000104,  100000105,  100000106,  
                100000159,  100000112,  100000135,  100000090,  100000113,  
                100000141,  100000146,  100000115,  100000108,  100000092,  
                100000155,  100000125,  100000151,  100000136,  100000107,  
                100000142) 
   ) AS e ON e.User_Id = b.User_Id
LEFT JOIN 
   (SELECT 
        USER_ID, CallStartDt, SeqNum
    FROM 
        [detail_epro].[dbo].[AgentDispoDetail]
    WHERE Disp_Id IN 
                (100000150, 100000137,  100000093,  100000133,  100000123,  
                100000094,  100000161,  100000085,  100000086,  100000157,  
                100000088,  100000131,  100000160,  100000156,  100000165,  
                100000166,  100000122,  100000121,  100000138,  100000144,  
                100000132,  100000098,  100000100,  100000153,  100000139,  
                100000145,  100000101,  100000140,  100000102,  100000103,  
                100000105,  100000106,  100000159,  100000112,  100000135,  
                100000141,  100000146,  100000115,  100000108,  100000092,  
                100000155,  100000125,  100000151,  100000136,  100000107) 
   ) AS es ON es.User_Id = b.User_Id
WHERE
   (CONVERT(varchar, DATEADD(hh, - 7, b.CallStartDt), 101)) = (CONVERT(varchar, DATEADD(hh, - 7, c.CallStartDt), 101))
   AND (CONVERT(varchar, DATEADD(hh, - 7, b.CallStartDt), 101))= (CONVERT(varchar, DATEADD(hh, - 7, d.CallStartDt), 101))
   AND (CONVERT(varchar, DATEADD(hh, - 7, b.CallStartDt), 101))= (CONVERT(varchar, DATEADD(hh, - 7, e.CallStartDt), 101)) 
   AND (CONVERT(varchar, DATEADD(hh, - 7, b.CallStartDt), 101))= (CONVERT(varchar, DATEADD(hh, - 7, es.CallStartDt), 101))
   AND (CONVERT(varchar, DATEADD(hh, - 7, b.CallStartDt), 101)) >= '08/01/2014'
GROUP BY
   b.User_Id, b.CallStartDt
Run Code Online (Sandbox Code Playgroud)

这比我想要运行这个查询需要更长的时间,一分钟之内,我猜它与服务器有很多关系,但我想要看看是否有人有任何想法让这更快

查询是获取一些未被任何表汇总的电话代理数据

  • acd =入站呼叫
  • aod =拨打电话
  • 手动=手动呼叫
  • contacts =基于代理人将使用的处理代码
  • success =是联系人的子集

ype*_*eᵀᴹ 6

查询存在许多问题,但我注意到的第一件事是日期时间转换效率低下.因此,在检查索引和执行计划之前,我首先从该部分开始.

我想您要检查各个日期时间是否在同一天(减去7小时,这可能是您的时区,而数据以UTC格式存储).所以,试试这个,而不是那个(可怕的)WHERE:

CROSS APPLY
    ( SELECT dt = DATEADD(hour, -7, b.CallStartDt) ) AS x
CROSS APPLY
    ( SELECT dt = DATEADD(day, +1, x.dt) ) AS y
WHERE
       b.CallStartDt >= DATEADD(hour, +7, '20140801')
  AND  c.CallStartDt >= x.dt AND  c.CallStartDt < y.dt
  AND  d.CallStartDt >= x.dt AND  d.CallStartDt < y.dt
  AND  e.CallStartDt >= x.dt AND  e.CallStartDt < y.dt
  AND es.CallStartDt >= x.dt AND es.CallStartDt < y.dt
Run Code Online (Sandbox Code Playgroud)

说明/注意事项:

  • (CONVERT(varchar, DATEADD(hh, - 7, b.CallStartDt), 101)) >= '08/01/2014'是完全错误的.它不仅使用效率低下的转换,而且还会返回错误的结果.因为日期(作为字符串和日期)'08/03/2014'都在之后,'08/01/2014'但是对于其他示例,它是相反的方式:'09/09/2011' > '08/01/2014'但显然2011年是在2014年之前.

  • 所有不必要的来电DATEDIFF()CONVERT()已被删除.这样,如果这些列上有索引,则不仅会对函数执行几千次调用(或百万次,取决于您的表大小),而且优化器将能够使用各种条件的索引.

  • b.CallStartDt保留了(-7小时),因为如果不改变表格就没有办法避免这种情况(添加带索引的计算列虽然有帮助.)

  • 使用理智的日期和日期时间格式,如'20140801'('YYYYMMDD'),正如Aaron Bertrand的博客所解释的那样是在SQL-Server中使用日期的唯一100%安全格式.请参阅:糟糕的习惯:错误处理日期/范围查询

  • 使用该DATEADD()功能,使用长形式.hour代替hh,day代替dd,minute而不是mm(或者是mi?,或min?,我一直忘了.)不容易出错.

更多事情要做:

  • 上述4个条件(那些关于c,d,ees表)可能应该被移动到相应的LEFT连接(如DRapp评论).

  • 检查执行计划以及索引是否可用和使用.

末节:

  • @第十二.日Thnx.我想你在谈论'CROSS APPLY`.这可以改变,但表达式必须写四次.这不是效率问题,只是代码少一点. (2认同)