在大表上加速 Count(*)

Zac*_*her 8 sql-server count sql-server-2012

我们正在使用在 SQL Server Enterprise 上运行的供应商应用程序,它COUNT在处理大多数财务文档(订单、发票等)时在 Items 表上执行语句有一个相当烦人的怪癖。

例如 SELECT COUNT('A') FROM [dbo].[Items] T0

我相信这通常没问题,但是有超过 600 万条记录,并且需要大约 400 毫秒来计算它们。这可能构成整个处理时间的很大一部分。

该表已经有一个非常窄的非聚集索引(tinyint,加上聚集键),这是 SQL 在执行表扫描时使用的,所以我认为我们在这方面不能做得更好。

我知道有一些解决方案,如果可能,我们希望避免:

我们还有其他选择可以加快速度吗?

这是显示设置的要点:https : //gist.github.com/elvishfiend/5094f120b14f8ecfb325623edcb5f3eb

Pau*_*ite 14

如果以最佳方式实施,索引视图应该是最快的选项之一,具有最低的维护开销。

正如我在执行计划中的索引视图维护中详细解释的那样,修改是增量(增量)(不会对每个基表更新执行完整的重新计数);但是,您确实需要确保执行计划的增量更新部分具有有效的访问方法(如任何查询)。

INSERT/UPDATE/DELETE执行计划中识别缺失的索引通常非常简单。也许您可以在问题中添加说明性的执行后(实际)执行计划。

查询文本与索引视图的自动匹配仅在企业版(和同等版本)中可用。在其他版本中,您必须使用WITH (NOEXPAND)表提示。即使在企业版上也有很好的理由使用NOEXPAND

关于演示代码:确保使用WITH (NOEXPAND). 您编写它的方式NOEXPAND被解析为别名。另请注意,只有物化(索引)视图可以有NOEXPAND提示。

如果您无法直接添加提示,这将是计划指南的绝佳用途。计划指南还可用于确保与索引视图匹配的查询(无需明确命名)实际使用索引视图。

请记住,如果没有NOEXPAND物化(索引)视图,SQL Server 总是在计划编译开始时扩展视图定义。企业版可能(也可能不)将查询(部分)与索引视图匹配,具体取决于其对每个选项成本的评估。

相关问答:


Joe*_*ish 6

如果您坚持使用 SQL Server 2012,您可以尝试仅在聚集索引键上创建索引。它可能比TINYINT列上的索引小一点。您也可以尝试向索引添加页面压缩。这可能会使您的查询更快,但这取决于表中的数据。

如果您能够升级到 SQL Server 2016,则可以在表上创建非聚集列存储索引。这将使COUNT(*)查询速度极快,同时降低 DML 操作的开销。这是一个快速演示:

DROP TABLE IF EXISTS #Items;

CREATE TABLE #Items (
    CLUST_KEY BIGINT NOT NULL,
    SMALL_COLUMN TINYINT NOT NULL,
    FILLER VARCHAR(50) NOT NULL,
    PRIMARY KEY (CLUST_KEY)
);

INSERT INTO #Items WITH (TABLOCK)
SELECT
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    , 1
    , REPLICATE('Z', 50)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

CREATE INDEX NCI ON #Items (SMALL_COLUMN);

SET STATISTICS TIME ON;

-- CPU time = 312 ms,  elapsed time = 320 ms.
SELECT COUNT(*)
FROM #Items
OPTION (MAXDOP 1);


CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI ON #Items (SMALL_COLUMN);

-- CPU time = 0 ms,  elapsed time = 1 ms.
SELECT COUNT(*)
FROM #Items
OPTION (MAXDOP 1);
Run Code Online (Sandbox Code Playgroud)

使用 NCCI,我可以在 20 毫秒内计算出 600 万行。


归档时间:

查看次数:

10009 次

最近记录:

7 年,7 月 前