SQL Server大型临时表COUNT(*)过慢,求高效行数统计方案
临时表高效统计行数的方案
替代sys.sysindexes的临时表查询方法
你用来查普通表的sys.sysindexes是旧版系统视图,临时表的元数据存储在tempdb中,用以下方法可以快速获取行数,无需扫描全表:
方法1:用sys.dm_db_partition_stats(推荐)
这个视图直接读取SQL Server维护的分区行数统计,本地/全局临时表都适用:
SELECT OBJECT_NAME(object_id) AS table_name, SUM(row_count) AS number_of_rows FROM sys.dm_db_partition_stats WHERE object_id = OBJECT_ID('tempdb..#your_temp_table') AND index_id IN (0, 1) -- 0对应堆表,1对应聚集索引,覆盖所有表类型 GROUP BY object_id;
该方法速度极快,唯一需要注意:如果临时表刚完成大量增删改操作,统计信息可能存在滞后,此时先执行UPDATE STATISTICS #your_temp_table;再查询即可。
方法2:查询tempdb的sys.tables + sys.partitions
本地临时表在tempdb中的名称会自动添加随机后缀(比如#table____00000000004C),因此需要用LIKE匹配:
SELECT t.name, SUM(p.rows) AS number_of_rows FROM tempdb.sys.tables t JOIN tempdb.sys.partitions p ON t.object_id = p.object_id WHERE t.name LIKE '#your_temp_table%' AND p.index_id IN (0, 1) GROUP BY t.name;
如果是全局临时表,直接用t.name = '##your_global_temp_table'即可,无需LIKE匹配。
你提到的ROW_NUMBER方案不可行
你写的这段代码:
Select Top 1 rn From (Select *, ROW_NUMBER() Over (Order by (Select NULL) ) As rn From geschaeft.SPOTGeschaeftstammMonat ) As a Order by rn Desc
本质还是要扫描全表生成行号,和count(*)一样需要遍历所有数据,数据量大时同样耗时,甚至因为要额外生成行号列,性能比count(*)更差,完全没有使用价值。
优化思路总结
- 优先使用系统统计视图:这是最快的统计方式,无需扫描全表,仅需关注统计信息的时效性,必要时手动更新。
- 避免全表扫描类方法:包括无索引的
count(*)、ROW_NUMBER这类逻辑,数据量大时耗时极高;若临时表有聚集索引,count(主键列)会比count(*)略快,但仍远不如读统计视图高效。 - 提前维护计数器:如果业务中需要频繁统计临时表行数,可以在插入/删除数据时维护一个变量,比如每次
INSERT后累加行数,要统计时直接读取变量即可,完全无查询耗时。
内容的提问来源于stack exchange,提问作者Boris
相关产品推荐
相关产品推荐

