当我需要知道某些列n
包含超过c
个重复项的行数时,我可以这样做:
WITH duplicateRows AS (
SELECT COUNT(1)
FROM [table]
GROUP BY c
HAVING COUNT(1) > n
) SELECT COUNT(1) FROM duplicateRows
这会导致不必要的行为:SQL Server会计算按i
分组的所有行,这些行(当此表中没有索引时)会导致可怕的性能。
但是,在更改脚本以使SQL Server不必计算所有行时,并不能解决问题:
WITH duplicateRows AS (
SELECT 1
FROM [table]
GROUP BY c
HAVING COUNT(1) > n
) SELECT COUNT(1) FROM duplicateRows
虽然理论上的SQL Server现在可以在n + 1
之后停止计数,但它会导致相同的查询计划和查询成本。
当然,原因是GROUP BY
确实引入了成本,而不是计算成本。但我对这些数字并不感兴趣。是否有另一种方法可以在没有索引的表上加快重复行的计数?
答案 0 :(得分:2)
查询中最大的两个成本是GROUP BY的重新排序(由于缺少适当的索引)以及您正在扫描整个表格。
不幸的是,要识别重复项,重新排序整个表是最便宜的选择。
您可能从以下更改中获益,但我非常怀疑它会有多大意义,因为我预计执行计划无论如何都会再次出现。
WITH
sequenced_data AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY fieldC) AS sequence_id
FROM
yourTable
)
SELECT
COUNT(*)
FROM
sequenced_data
WHERE
sequence_id = (n+1)
假设SQLServer2005 +
答案 1 :(得分:1)
没有索引GROUP BY解决方案是最好的,每个基于PARTITION的解决方案都涉及表(clust。索引)扫描和排序,而不是GROUP BY案例中的简单扫描和计数
答案 2 :(得分:1)
如果唯一的目标是确定任何组中是否存在任何行(或者,为了重新说明这一点,“在表中存在重复,给定列c
的区别”),添加{{ 1}} TOP(1)
查询可以执行一些性能魔术。
SELECT
理论上,SQL Server不需要确定所有组,因此只要找到具有重复的第一个组,查询就会完成(但最坏情况将与原始方法一样长)。我不得不说这是一种有点必要的思考方式 - 不确定它是否正确......
答案 3 :(得分:0)
速度和“没有索引”几乎从不在一起。
虽然这里的其他人已经提到过,但我非常怀疑它会带来性能上的好处。也许您可以尝试使用PARTITION BY重新构建查询。
例如:
WITH duplicateRows AS (
SELECT a.aFK,
ROW_NUMBER() OVER(PARTITION BY a.aFK ORDER BY a.aFK) AS DuplicateCount
FROM Address a
) SELECT COUNT(DuplicateCount) FROM duplicateRows
我没有针对实际的group by子句查询来测试它的性能。这只是建议你如何以另一种方式重组它。