加载选择查询的时间太长

时间:2018-01-17 09:53:52

标签: sql sql-server tsql sql-server-2016

我有一个查询,它需要大约1分40秒来提供输出,有时需要超过2或3分钟。任何人都可以帮助并告诉我为什么花了这么多时间?输出结果大约为409799行。

Select 
 Distinct
 A.ID
 ,tracactionId Contracid
 ,Cancaldate 
,Suppliers
,Ct.Type "Contract Type"
,Sitename "Site Name" 
,St.Telephone "Site Telephone"
,Cc.Mobile
,At.Type "Action Type"
,Ms.Status "Order Status"
,Name Client
,Ass.Status
 ,Isnull(
     Case When Try_Parse(orderac As Numeric(10,2)) <= '60000' Then 'T3' 
     When Try_Parse(orderac As Numeric(10,2)) >= '60001' And 
    Try_Parse(orderac As Numeric(10,2)) <= '1000000' Then 'T2' 
     When Try_Parse(orderac As Numeric(10,2)) >= '1000001'  Then 'T1' End, 
   '-') "Consumption Order"
   ,Isnull(
     Case When Try_Parse(Replaceaq As Numeric(10,2)) <= '60000' Then 'T3' 
     When Try_Parse(Replaceaq As Numeric(10,2)) >= '60001' And 
  Try_Parse(Replaceaq As Numeric(10,2)) <= '1000000' Then 'T2' 
     When Try_Parse(Replaceaq As Numeric(10,2)) >= '1000001'  Then 'T1' End, 
   '-') "Consumption Replace"
  ,Case When Datepart(Day, Cancaldate ) > 21 And Cancaldate  < '9999-12-01'
  Then Substring(Datename(Month, Dateadd(Month, 1, Cancaldate )), 1, 3) + ' 
  ' + Datename(Year, Dateadd(Month, 1, Cancaldate ))
  Else Substring(Datename(Month, Cancaldate ), 1, 3) + ' ' + Datename(Year, 
  Cancaldate ) End As "Month Year"
   From return A
   Left  Hash Join Contract C On C.Contractid = A.contractid
                                                 And orderdate In (Select 
  Max(Aa.orderdate) From Return Aa Where Aa.Contractid = A.Contractid)
 Left  Hash Join Suppliers S On S.Suppliersid = C.Supplierid
  Left  Hash Join ordercontract Mc On Mc.Contractid = C.Contractid
 Left  Hash Join order M On M.orderid = Mc.orderid
 Left  Hash Join Contracttype Ct On C.Contracttypeid= Ct.ordercontracttypeid
 Left  Hash Join Site St On St.Siteid = C.Siteid
  Inner Hash Join ordersubtype Ast On Ast.ordersubtypeid = A.Aordersubtypeid
 Inner Hash Join ordertype At On At.ordertypeid = A.ordertypeid
 Left  Hash Join oderstatus Ms On Ms.orderstatusid = M.orderstatusid 
  Inner Hash Join Users U On U.Userid = A.userid
 Inner Hash Join orderstatus Ass On Ass.orderstatusid = A.orderstatusid
 Inner Hash Join product On A.productid = product.productid
 Inner Hash Join Contact Cc On product.Maincontactid = Cc.Contactid
 where  M.Meterstatusid <> 8 

这是执行计划及其建议创建非聚集索引。

我是新手;请帮帮我。

/*
Missing Index Details from SQLQuery2.sql - 10.0.1.9.EnergyCRM_Main 
(adminlocal (84))
 The Query Processor estimates that implementing the following index could 
 improve the query cost by 15.558%.
 */

  /*
 USE [SAmpler]
   GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
 ON [dbo].[Action] ([orderID])
INCLUDE ([orderTypeID],[orderStatusID],[productID],[orderDate],
 [AssignedToUserID],[orderSubTypeID])
  GO
  */

3 个答案:

答案 0 :(得分:3)

如果没有执行计划,这个问题很难回答。 看看代码我怀疑了几件事情;

  • ISNULL在索引列上使用时通常会损害性能,因为它禁止使用所述索引

  • 为什么所有连接都指定为散列连接?在大多数情况下,最好让查询优化器决定哪个连接最快。

  • 我看到很多try_parse,可能需要事先检查/处理列并将它们设置为所需的数据类型。在这种情况下,如果它是正确的数据类型,则不必检查每个列。

答案 1 :(得分:0)

这只是猜测,因为我们无法执行实际查询。我最好的猜测是你所有的ISNULL都在损害性能。

试试这个:

Case When Try_Parse(orderac As Numeric(10,2)) <= '60000' Then 'T3' 
     When Try_Parse(orderac As Numeric(10,2)) >= '60001' And 
     Try_Parse(orderac As Numeric(10,2)) <= '1000000' Then 'T2' 
     When Try_Parse(orderac As Numeric(10,2)) >= '1000001'  Then 'T1' 
     ELSE '-' End AS "Consumption Order"

答案 2 :(得分:0)

只是弄清楚这个烂摊子

您需要指明列来自哪些表 不清楚所有表格都被使用

所有Try_Parse都是个问题

表连接提示应该是最后的手段

Select Distinct
       A.ID
     , tracactionId Contracid
     , Cancaldate 
     , Suppliers
     , Ct.Type "Contract Type"
     , Sitename "Site Name" 
     , St.Telephone "Site Telephone"
     , Cc.Mobile
     , At.Type "Action Type"
     , Ms.Status "Order Status"
     , Name Client
     , Ass.Status  
     , Isnull( Case When Try_Parse(orderac As Numeric(10,2)) <= '60000'   Then 'T3'
                    When Try_Parse(orderac As Numeric(10,2)) >= '60001' 
                     And Try_Parse(orderac As Numeric(10,2)) <= '1000000' Then 'T2' 
                    When Try_Parse(orderac As Numeric(10,2)) >= '1000001' Then 'T1' 
               End
               , '-'
             ) "Consumption Order"
     , Isnull( Case When Try_Parse(Replaceaq As Numeric(10,2)) <= '60000' Then 'T3'
                    When Try_Parse(Replaceaq As Numeric(10,2)) >= '60001' 
                     And Try_Parse(Replaceaq As Numeric(10,2)) <= '1000000' Then 'T2' 
                    When Try_Parse(Replaceaq As Numeric(10,2)) >= '1000001' Then 'T1' 
               End
               , '-'
             ) "Consumption Replace"
    , Case When Datepart(Day, Cancaldate ) > 21 And Cancaldate  < '9999-12-01'  
                Then Substring(Datename(Month, Dateadd(Month, 1, Cancaldate )), 1, 3) 
                     + ' ' + Datename(Year, Dateadd(Month, 1, Cancaldate ))
           Else Substring(Datename(Month, Cancaldate ), 1, 3) 
                + ' ' + Datename(Year, Cancaldate ) 
      End As "Month Year"
From return A

Inner Hash Join ordersubtype Ast On Ast.ordersubtypeid = A.Aordersubtypeid

Inner Hash Join ordertype At     On At.ordertypeid     = A.ordertypeid 

Inner Hash Join orderstatus Ass  On Ass.orderstatusid  = A.orderstatusid

Inner Hash Join Users U On U.Userid                    = A.userid

Inner Hash Join product On product.productid           = A.productid 
Inner Hash Join Contact Cc On Cc.Contactid = product.Maincontactid 

Left Hash Join Contract C 
  On C.Contractid                                      = A.contractid
 And orderdate In ( Select Max(Aa.orderdate) 
                    From Return Aa 
                    Where Aa.Contractid = A.Contractid 
                  )
Left  Hash Join Suppliers S On S.Suppliersid               = C.Supplierid      
Left  Hash Join Contracttype Ct On  Ct.ordercontracttypeid = C.Contracttypeid    
Left  Hash Join Site St On St.Siteid                       = C.Siteid

Left  Hash Join ordercontract Mc On Mc.Contractid          = C.Contractid  
Left  Hash Join order M On M.orderid = Mc.orderid
Left  Hash Join oderstatus Ms On Ms.orderstatusid = M.orderstatusid 

where  M.Meterstatusid <> 8 
相关问题