优化需要花费数小时才能执行的查询

时间:2016-03-18 10:49:14

标签: sql sql-server sql-server-2008

如何优化以下查询:

 SELECT CASE
           WHEN COUNT(DISTINCT t1.[datecol]) = 0
               THEN 0
           ELSE SUM(CONVERT(FLOAT, Quantité)) / COUNT(DISTINCT t1.[datecol])
       END AS QTEMOY,
       CASE
           WHEN COUNT(DISTINCT t1.[datecol]) = 0
               THEN 0
           ELSE SUM(CONVERT(FLOAT, [Prix de vente TTC])) / COUNT(DISTINCT t1.[datecol])
       END AS CAMOY,
       t1.[Code Article],
       t1.[Code Structure],
       t1.[Code Site]
FROM [Vente ] t1
OUTER APPLY (
    SELECT DISTINCT TOP 28 t2.[datecol]
    FROM [Vente ] t2
    WHERE t2.[Code Article] = t1.[Code Article] AND t2.[Code Structure] = t1.[Code Structure] AND t2.[Code Site] = t1.[Code Site]
        AND NOT EXISTS (
            SELECT [Code Article]
            FROM [Promotion ] a
            WHERE t2.datecol BETWEEN [Date Debut Promo] AND [Date Fin Promo] AND t2.[Code Article] = a.[Code Article]
        )
   ORDER BY t2.[datecol] DESC
) t2
WHERE NOT EXISTS (SELECT t1.[Code Article] FROM [Promotion ] b WHERE t1.datecol BETWEEN [Date Debut Promo] AND [Date Fin Promo] AND t1.[Code Article] = b.[Code Article])
    AND (t1.[Code Article] IS NOT NULL)
    AND (t1.[Code Structure] IS NOT NULL)
    AND (t1.[Prix de Revient] IS NOT NULL)
    AND t1.datecol = t2.datecol
    AND t1.[Code Article] IN (SELECT [Code Article] FROM [Reference] t)
GROUP BY t1.[Code Article],
         t1.[Code Structure],
         t1.[Code Site]

查询需要花费数小时才能优化它?

StmtText
  |--Compute Scalar(DEFINE:([Expr1017]=CASE WHEN [Expr1014]=(0) THEN (0.000000000000000e+000) ELSE [Expr1015]/CONVERT_IMPLICIT(float(53),[Expr1014],0) END, [Expr1018]=CASE WHEN [Expr1014]=(0) THEN (0.000000000000000e+000) ELSE [Expr1016]/CONVERT_IMPLICIT(float(53),[Expr1014],0) END))
       |--Compute Scalar(DEFINE:([t1].[Code Article]=[Expr1025], [t1].[Code Structure]=[Expr1026], [t1].[Code Site]=[Expr1027]))
            |--Hash Match(Inner Join, HASH:([Expr1025], [Expr1026], [Expr1027])=([Expr1022], [Expr1023], [Expr1024]), RESIDUAL:([Expr1022] = [Expr1025] AND [Expr1023] = [Expr1026] AND [Expr1024] = [Expr1027]))
                 |--Compute Scalar(DEFINE:([Expr1025]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Article] as [t1].[Code Article], [Expr1026]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Structure] as [t1].[Code Structure], [Expr1027]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Site] as [t1].[Code Site]))
                 |    |--Compute Scalar(DEFINE:([Expr1014]=CONVERT_IMPLICIT(int,[Expr1046],0)))
                 |         |--Stream Aggregate(GROUP BY:([t1].[Code Article], [t1].[Code Structure], [t1].[Code Site]) DEFINE:([Expr1046]=Count(*)))
                 |              |--Sort(DISTINCT ORDER BY:([t1].[Code Article] ASC, [t1].[Code Structure] ASC, [t1].[Code Site] ASC, [t1].[datecol] ASC))
                 |                   |--Table Spool
                 |                        |--Parallelism(Gather Streams)
                 |                             |--Filter(WHERE:([Expr1019]=[Expr1007]))
                 |                                  |--Nested Loops(Left Outer Join, OUTER REFERENCES:([t1].[Code Site], [t1].[Code Article], [t1].[Code Structure]))
                 |                                       |--Hash Match(Right Anti Semi Join, HASH:([b].[Code Article])=([t1].[Code Article]), RESIDUAL:([Expr1019]>=[QlikDataWarehouse].[dbo].[Promotion Geant].[Date Debut Promo] as [b].[Date Debut Promo] AND [Expr1019]<=[QlikDataWarehouse].[dbo].[Promotion Geant].[Date Fin Promo] as [b].[Date Fin Promo] AND [QlikDataWarehouse].[dbo].[Vente Geant].[Code Article] as [t1].[Code Article]=[QlikDataWarehouse].[dbo].[Promotion Geant].[Code Article] as [b].[Code Article]))
                 |                                       |    |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([b].[Code Article]))
                 |                                       |    |    |--Index Scan(OBJECT:([QlikDataWarehouse].[dbo].[Promotion Geant].[id_date] AS [b]))
                 |                                       |    |--Compute Scalar(DEFINE:([Expr1019]=[QlikDataWarehouse].[dbo].[Vente Geant].[datecol] as [t1].[datecol], [Expr1020]=CONVERT(float(53),[QlikDataWarehouse].[dbo].[Vente Geant].[Quantité] as [t1].[Quantité],0), [Expr1021]=CONVERT(float(53),[QlikDataWarehouse].[dbo].[Vente Geant].[Prix de vente TTC] as [t1].[Prix de vente TTC],0)))
                 |                                       |         |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([t1].[Code Article]))
                 |                                       |              |--Nested Loops(Inner Join, OUTER REFERENCES:([t1].[ID], [Expr1045]) OPTIMIZED WITH UNORDERED PREFETCH)
                 |                                       |                   |--Nested Loops(Inner Join, OUTER REFERENCES:([t].[Code Article], [Expr1044]) WITH UNORDERED PREFETCH)
                 |                                       |                   |    |--Stream Aggregate(GROUP BY:([t].[Code Article]))
                 |                                       |                   |    |    |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([t].[Code Article]), ORDER BY:([t].[Code Article] ASC))
                 |                                       |                   |    |         |--Index Scan(OBJECT:([QlikDataWarehouse].[dbo].[Reference].[Id_ref] AS [t]), ORDERED FORWARD)
                 |                                       |                   |    |--Index Seek(OBJECT:([QlikDataWarehouse].[dbo].[Vente Geant].[Id_SuiviRupture] AS [t1]), SEEK:([t1].[Code Article]=[QlikDataWarehouse].[dbo].[Reference].[Code Article] as [t].[Code Article] AND [t1].[Prix de Revient] IsNotNull),  WHERE:([QlikDataWarehouse].[dbo].[Vente Geant].[Code Article] as [t1].[Code Article] IS NOT NULL AND [QlikDataWarehouse].[dbo].[Vente Geant].[Code Structure] as [t1].[Code Structure] IS NOT NULL) ORDERED FORWARD)
                 |                                       |                   |--Clustered Index Seek(OBJECT:([QlikDataWarehouse].[dbo].[Vente Geant].[PK_Vente Geant] AS [t1]), SEEK:([t1].[ID]=[QlikDataWarehouse].[dbo].[Vente Geant].[ID] as [t1].[ID]) LOOKUP ORDERED FORWARD)
                 |                                       |--Top(TOP EXPRESSION:((28)))
                 |                                            |--Sort(DISTINCT ORDER BY:([Expr1007] DESC))
                 |                                                 |--Nested Loops(Left Anti Semi Join, WHERE:([Expr1007]>=[QlikDataWarehouse].[dbo].[Promotion Geant].[Date Debut Promo] as [a].[Date Debut Promo] AND [Expr1007]<=[QlikDataWarehouse].[dbo].[Promotion Geant].[Date Fin Promo] as [a].[Date Fin Promo]))
                 |                                                      |--Index Spool(SEEK:([t2].[Code Article]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Article] as [t1].[Code Article] AND [t2].[Code Structure]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Structure] as [t1].[Code Structure] AND [t2].[Code Site]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Site] as [t1].[Code Site]))
                 |                                                      |    |--Compute Scalar(DEFINE:([Expr1007]=[QlikDataWarehouse].[dbo].[Vente Geant].[datecol] as [t2].[datecol]))
                 |                                                      |         |--Index Scan(OBJECT:([QlikDataWarehouse].[dbo].[Vente Geant].[Id_SuiviRupture] AS [t2]))
                 |                                                      |--Clustered Index Seek(OBJECT:([QlikDataWarehouse].[dbo].[Promotion Geant].[PROMOG_CodeArtIndex] AS [a]), SEEK:([a].[Code Article]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Article] as [t1].[Code Article]) ORDERED FORWARD)
                 |--Compute Scalar(DEFINE:([Expr1022]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Article] as [t1].[Code Article], [Expr1023]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Structure] as [t1].[Code Structure], [Expr1024]=[QlikDataWarehouse].[dbo].[Vente Geant].[Code Site] as [t1].[Code Site]))
                      |--Compute Scalar(DEFINE:([Expr1015]=CASE WHEN [Expr1047]=(0) THEN NULL ELSE [Expr1048] END, [Expr1016]=CASE WHEN [Expr1049]=(0) THEN NULL ELSE [Expr1050] END))
                           |--Stream Aggregate(GROUP BY:([t1].[Code Article], [t1].[Code Structure], [t1].[Code Site]) DEFINE:([Expr1047]=COUNT_BIG([Expr1020]), [Expr1048]=SUM([Expr1020]), [Expr1049]=COUNT_BIG([Expr1021]), [Expr1050]=SUM([Expr1021])))
                                |--Sort(ORDER BY:([t1].[Code Article] ASC, [t1].[Code Structure] ASC, [t1].[Code Site] ASC))
                                     |--Table Spool

1 个答案:

答案 0 :(得分:0)

单独查看查询我可以看到一些性能问题:

  1. 使用OUTER APPLY和SELECT DISTINCT以及子查询。每个子查询都将作为嵌套循环操作执行,因此每个OUTER APPLY都会执行。这意味着需要进行多次额外操作 - 循环多次。

  2. 有很多子查询,导致1中定义的问题。