【问题标题】:SQL Group By with Count is slowSQL Group By with Count 很慢
【发布时间】:2014-06-03 01:29:21
【问题描述】:

我有一个包含近 300 万行的表,每秒有 5-10 次更新/插入。每行都分配了一个类别,我想按类别分组以计算每个类别的总行数。

Select CategoryId
     , COUNT(*) as TotalRows
  FROM Table1
 WHERE SaleTypeId = 2 AND CategoryId > 1
 GROUP BY CategoryId

表架构:

CREATE TABLE [dbo].[Table1](
[SaleId]      INT IDENTITY (1, 1) NOT NULL,
[SaleTypeId]  INT                 NOT NULL,
[CategoryId]  INT                 NULL)

主键:

 ADD CONSTRAINT [PK_Table1] 
 PRIMARY KEY CLUSTERED ([SaleId] ASC) 
 WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, 
       IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF);

我的表上有一个非聚集索引:

CREATE NONCLUSTERED INDEX [Index1] ON [dbo].[Table1]
(
    [SaleTypeId] ASC,
    [CategoryId] ASC    
)

查询计划:

查询需要 40 到 60 秒才能运行,并且看起来在索引查找操作中正在读取大量数据。有什么办法可以加快这个查询?我读过在更大的数据集上计数会变慢,并且有更快的方法来获取整个表的计数,但我需要按类别获取计数。

【问题讨论】:

  • 添加聚集索引肯定会有帮助。
  • 图表显示索引查找发生在不是 idx_SaleCategory 的 Table1.Index1 上。您似乎没有从新索引中受益。
  • @M.Ali - 这将有助于 此查询,但总体上可能是聚集索引的错误选择。
  • 您也可以尝试添加WITH NOLOCK。如果您每秒获得多个更新,您可能会遇到争用。
  • 使用 COUNT(CategoryId) 而不是 COUNT(*)。

标签: sql sql-server performance


【解决方案1】:

反转非聚集索引中的列顺序,如下所示:

CREATE NONCLUSTERED INDEX [Index1] ON [dbo].[Table1]
(
    [CategoryId] ASC,    
    [SaleTypeId] ASC
)

【讨论】:

  • 为什么推荐这个?据我了解,应该首先在索引中使用相等列,然后是不等列。当我使用反向索引运行查询时,执行计划建议创建原始索引。
  • 您是否查看过索引,看看它是否严重碎片化并需要重建?
  • 我推荐它是因为SaleType = 2 似乎不太挑剔。现在不知道值得尝试的实际密度。问题是您必须(按顺序)阅读大部分索引,一个或另一个;没有其他方法可以计算 CategoryId 上的聚合,无论如何这两个列上都应该有一个 NC 索引,这只是选择性问题。
  • 明白了。所以看来我运气不好?我知道计数可能很慢,但这似乎是一件微不足道的事情。
  • @DaveJemison 索引确实碎片化了,但它每晚都会进行碎片整理。问题中的执行计划是在碎片整理后立即运行。
【解决方案2】:

尝试运行它,我也会按照@dean 的建议放置索引

Select CategoryId, COUNT(CategoryId) as TotalRows
 FROM Table1 WITH (NOLOCK)
 WHERE SaleTypeId = 2 AND CategoryId > 1
 GROUP BY CategoryId

【讨论】:

    【解决方案3】:

    我最终将其作为夜间聚合作业运行,并将结果存储在聚合表中。它没有提供最新的结果(经过深思熟虑,我们可以接受),夜间查询也没有更快,但是从聚合表中读取要快得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-07
      • 2020-08-02
      • 2018-06-17
      • 1970-01-01
      • 2023-02-01
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多