Tengo una consulta, y me está tomando alrededor de 1 minuto y 40 segundos dar salida y en algún momento tomar más de 2 o 3 minutos. ¿Alguien puede ayudarme y decirme por qué está tomando tanto tiempo? El resultado de salida es de alrededor de 409799 filas.

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 

Este es el plan de ejecución y su sugerencia para crear un índice no agrupado.

Soy nuevo en esto; Por favor, ayúdame.

/*
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
  */
-1
Skorpion 17 ene. 2018 a las 12:53

3 respuestas

La mejor respuesta

Solo dando sentido a este desastre

Debe indicar de qué tablas provienen las columnas
No está claro, todas las tablas se usan

Toda la Try_Parse es un problema

Las sugerencias de unión de tabla deberían ser el último recurso

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 
0
paparazzo 17 ene. 2018 a las 14:18

Esta pregunta es realmente difícil de responder sin un plan de ejecución. Mirando el código sospecho un par de cosas;

  • ISNULL generalmente perjudica el rendimiento cuando se usa en columnas indexadas ya que prohíbe el uso de dichos índices

  • ¿Por qué todas las combinaciones se especifican como combinaciones hash? En la mayoría de los casos, es mejor dejar que el optimizador de consultas decida qué combinación es la más rápida.

  • Veo mucho try_parse, podría ser una consideración verificar / procesar las columnas de antemano y establecerlas en el tipo de datos deseado. En ese caso, no tiene que verificar cada columna si es el tipo de datos correcto.

3
ppijnenburg 17 ene. 2018 a las 10:25

Esto es solo una suposición, ya que no podemos realizar la consulta real. Mi mejor conjetura es que todos sus ISNULL están perjudicando el rendimiento.

Prueba esto:

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"
0
SQL_M 17 ene. 2018 a las 10:06