【问题标题】:sql server 2008 slow query on sumsql server 2008 对 sum 的慢查询
【发布时间】:2014-11-16 22:11:07
【问题描述】:

我不熟悉必须管理我们的 sqlserver 数据库。已收到此请求。

我有一个包含一百万条记录的大表。想要运行此报告。使用 SQL Server 2008 需要一个多小时。

rowid 是 PK 并且在 dx 和 varcharfield 上有一个索引。

SELECT T1.VarcharField,
       T1.DX,
       T1.ROWID,
       (SELECT Sum(t2.QC) AS Total
        FROM   tbl t2
        WHERE  T2.VarcharField = T1.VarcharField
               AND t2.dx <= t1.dx) AS Total
FROM   tbl AS T1 

【问题讨论】:

  • 这种计算运行总数的方法不能扩展到 100 万行。

标签: sql-server sql-server-2008 cumulative-sum


【解决方案1】:

这一切在 SQL Server 2012 中变得容易得多。

SELECT T1.VarcharField,
       T1.DX,
       T1.ROWID,
       SUM(QC) OVER (PARTITION BY VarcharField ORDER BY DX) AS Total
FROM   tbl AS T1 

因为你在 2008 年,上面的语法不起作用,你可以尝试添加这个索引

CREATE INDEX ix ON tbl(VarcharField,DX) INCLUDE (ROWID, QC)

然后使用以下查询

WITH RecursiveCTE
     AS (SELECT VarcharField,
                DX,
                ROWID,
                QC,
                QC AS Total
         FROM   (SELECT *,
                        ROW_NUMBER() OVER (PARTITION BY VarcharField ORDER BY DX) AS RN
                 FROM   tbl) T
         WHERE  RN = 1
         UNION ALL
         SELECT R.VarcharField,
                R.DX,
                R.ROWID,
                R.QC,
                R.Total
         FROM   (SELECT T.*,
                        T.QC + Total AS Total,
                        rn = ROW_NUMBER() OVER (ORDER BY T.DX)
                 FROM   tbl T
                        JOIN RecursiveCTE R
                          ON R.VarcharField = T.VarcharField
                             AND R.DX < T.DX) R
         WHERE  R.rn = 1)
SELECT VarcharField,
       DX,
       ROWID,
       Total
FROM   RecursiveCTE
OPTION (MAXRECURSION 0); 

【讨论】:

  • 这行得通。我添加了上面的索引。在 tbl(VarcharField,DX) 上创建索引 ix 包含 (ROWID, QC) 选择 T1.VarcharField , T1.DX, t1.rowid, Total = ( SELECT Sum(t2.QC) AS Total FROM tbl t2 WHERE t2.VarcharField = T1 .VarcharField And t2.dx
  • @kdigman 添加t2.rowid=t1.rowid 会大大改变语义。
【解决方案2】:

我认为这会运行得更快:

SELECT
  T1.VarcharField,
  T1.DX,
  T1.ROWID,
  SUM(t2.QC) AS Total
FROM
  tbl t2
  JOIN tb1 T1 ON T2.VarcharField = T1.VarcharField
GROUP BY 
  T1.VarcharField,
  T1.DX,
  T1.ROWID
WHERE
  t2.dx <= t1.dx

【讨论】:

  • 它将与 OP 的问题相同。问题是 1,000,000 个组平均每个 SUM 500,000 个值。总计 5000 亿个值。
  • 我没有尝试,但也许删除 where 子句并将该条件放在 join 中有助于提高速度。
  • 我认为 SUM 表示为子选择会比更直接的分组查询方法慢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 2020-01-27
相关资源
最近更新 更多