我曾经读过一些文章,说当表有很多行和很多列时,SELECT COUNT(*) FROM TABLE_NAME将会很慢。

我有一个可能包含数十亿行的表(它大约有15列)。有没有更好的方法来获得一个表的行数的精确计数?

在回答之前请考虑以下问题:

我正在寻找一个数据库供应商 独立的解决方案。如果是也可以 涵盖MySQL, Oracle, MS SQL Server。 但如果真的没有数据库 供应商独立的解决方案,然后我 会接受不同的解决方案吗 针对不同的数据库供应商。 我不能使用任何外部工具 这样做。我主要是在找一个 基于SQL的解决方案。 我不能规范化我的数据库设计 任何进一步的。它已经在3NF中,而且 很多代码已经写好了 围绕它。


当前回答

如果SQL Server版本是2005/2008,您可以使用dmv来计算表中的行数:

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name, 
 ddps.row_count 
FROM sys.indexes AS i 
 INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID 
 INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID 
 AND i.index_id = ddps.index_id 
WHERE i.index_id < 2 
 AND o.is_ms_shipped = 0 
ORDER BY o.NAME 

对于SQL Server 2000数据库引擎,sysindexes可以工作,但强烈建议避免在将来的SQL Server版本中使用它,因为它可能在不久的将来被删除。

示例代码摘自:如何快速轻松地获取表行计数

其他回答

如果你正在使用Oracle,那么这个怎么样(假设表的统计信息更新了):

select <TABLE_NAME>, num_rows, last_analyzed from user_tables

Last_analyzed将显示上次收集统计数据的时间。

我从另一个StackOverflow问题/答案得到这个脚本:

SELECT SUM(p.rows) FROM sys.partitions AS p
  INNER JOIN sys.tables AS t
  ON p.[object_id] = t.[object_id]
  INNER JOIN sys.schemas AS s
  ON s.[schema_id] = t.[schema_id]
  WHERE t.name = N'YourTableNameHere'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

我的表有5亿条记录,上面的返回时间不到1毫秒。 与此同时,

SELECT COUNT(id) FROM MyTable

整整39分52秒!

它们产生的行数完全相同(在我的例子中,正好是519326012)。

我不知道情况是否会一直如此。

使用SQL Server 2019,您可以使用APPROX_COUNT_DISTINCT,它:

返回组中唯一非空值的大致数目

医生说:

APPROX_COUNT_DISTINCT是为大数据场景而设计的 针对以下条件进行优化: 访问数百万行或更高的数据集 一个或多个具有不同值的列的聚合

还有,函数

实现保证在97%的概率内高达2%的错误率 比穷举COUNT DISTINCT操作需要更少的内存 与精确的COUNT DISTINCT操作相比,较小的内存占用不太可能将内存溢出到磁盘。

该算法背后实现了HyperLogLog。

嗯,晚了5年,不确定这是否有帮助:

我在试着数不。在SQL Server表中使用MS SQL Server Management Studio的行,并遇到了一些溢出错误,然后我使用下面的:

select count_big(1) FROM [dbname].[dbo].[FactSampleValue];

结果:

24296650578行

使用COUNT_BIG()获取一个非常大的文件中的记录计数。

SELECT COUNT_BIG(*) FROM TABLENAME;