12

我正在运行 SQL Server 2012。

我有一个查询,当条带化为最基本的形式时,如下所示:

SELECT COUNT(DISTINCT fullAddress) as quickCount 
FROM leads
WHERE yearID >=12 AND yearID <=21

潜在客户表中有大约 1.49 亿条记录。在leadID 上有一个聚集索引,在YearID 上有一个非聚集索引,并且包含fullAddress。

这个查询需要大约 40 秒才能运行。我意识到这还不错,但在这种情况下还不够快。

我查看了执行计划,据我所知,大约 60% 的成本是 DISTINCT COUNT。

当我像这样运行没有 DISTINCT COUNT 的相同查询时:

SELECT COUNT(*) as quickCount 
FROM leads
WHERE yearID >=12 AND yearID <=21

运行仅需 1 秒。

不幸的是,我需要计算不同的完整地址。所以我想弄清楚是否有什么办法可以让第一个查询运行得更快。

这是两个查询的执行计划的屏幕截图:

在此处输入图像描述

这是一个更大的链接 - http://www.sequenzia.com/execPlan.jpg

据我所知,我的主要问题是 Distinct Sort (52%)。

对此的任何帮助或反馈都会很棒。

谢谢!

更新

我接受了 Thilo 的建议并应用了这个索引:

 CREATE INDEX IDX_X ON LEADS(FULLADDRESS, YEARID);

我实际上创建了 2 个新的测试表,每个表都有完全相同的 100 万条记录。我将相同的原始索引应用于两者,然后将上述索引应用于其中一个。现在,当我比较同一执行计划上的 2 个表时,具有上述索引的表要好一些,为 48% 到 52%。这是新的执行计划 - http://www.sequenzia.com/execPlan2.jpg

这对一些人有帮助,但我真的需要更多的性能。还有其他想法吗?

4

4 回答 4

3

要尝试的一件事是通过对索引进行排序来摆脱排序fullAddress(这也包括yearID列,以便您也可以满足 where 子句)。

CREATE INDEX IDX_X ON LEADS(FULLADDRESS, YEARID);

这样,您应该获得快速全索引扫描(可能仍然比您对非明确计数的索引范围扫描慢,但希望比您的 40 秒排序更快)。

但是为什么需要这么快呢?这不是你需要一直做的事情,对吧?如果这是一个公共网站,我想你可以摆脱一个稍微过时的缓存结果。

于 2012-12-18T00:51:43.623 回答
2

此答案无助于解决原始问题(SQL Server 2012)。它适用于 Azure SQL DB 和 SQL Server 2019+。

## Approximate Count Distinct 在 Azure SQL 数据库中进入公共预览版

近似查询处理是一个新的功能系列,旨在提供跨非常大的数据集的聚合,其中响应能力比绝对精度更重要。...

新的 APPROX_COUNT_DISTINCT 聚合函数返回组中唯一非空值的大致数量。

##优点

与详尽的精确 COUNT DISTINCT 相比,APPROX_COUNT_DISTINCT 使用更少的内存来计算不同的计数。由于这个原因,即使数据集中有数十亿行,计算也更有可能在内存中完成而不会溢出到磁盘。如果 COUNT DISTINCT 会耗尽内存并将数据溢出到 TempDB 从而导致非常大的性能损失,APPROX_COUNT_DISTINCT 通常不会溢出。

部分是由于没有将大型数据集溢出到 TempDB,部分是由于内部算法的结果,对于非常大的数据集,APPROX_COUNT_DISTINCT 将比 COUNT DISTINCT 执行得快得多。

更多在APPROX_COUNT_DISTINCT 文档

SELECT APPROX_COUNT_DISTINCT(fullAddress) as quickCount 
FROM leads
WHERE yearID >=12 AND yearID <=21
于 2018-07-17T19:12:59.443 回答
0

如果您不经常更新此表,您可以查看使用正在运行的查询创建索引视图 http://msdn.microsoft.com/en-us/library/aa933148(v=sql.80).aspx

于 2012-12-18T04:44:59.483 回答
0

在进行不同计数之前,我会尝试使用子查询进行过滤

WITH cte as (SELECT ID
FROM leads
WHERE yearID >=12 AND yearID <=21)
SELECT COUNT(DISTINCT fullAddress) as quickCount 
FROM leads
JOIN cte on cte.ID = leads.ID

这并不总是在每种情况下都执行得更快,但据我所知,当您在没有执行不同操作的列上有 where 子句时,它会更快。

于 2021-03-03T22:25:54.017 回答