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

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

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

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


当前回答

我找到了一篇很好的文章:SQL Server-HOW-TO:快速从martijnh1检索表的准确行数,它很好地概述了每个场景。

我需要在需要根据特定条件提供计数的地方进行扩展,当我计算出这一部分时,我会进一步更新这个答案。

与此同时,以下是文章中的细节:

方法1:

查询:

SELECT COUNT(*) FROM Transactions 

评论:

执行全表扫描。在大桌子上慢点。

方法2:

查询:

SELECT CONVERT(bigint, rows) 
FROM sysindexes 
WHERE id = OBJECT_ID('Transactions') 
AND indid < 2 

评论:

快速检索行数的方法。取决于统计数据,不准确。

运行DBCC UPDATEUSAGE(数据库)WITH COUNT_ROWS,这对于大型表可能会花费大量时间。

方法3:

查询:

SELECT CAST(p.rows AS float) 
FROM sys.tables AS tbl 
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and
idx.index_id < 2 
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) 
AND p.index_id=idx.index_id 
WHERE ((tbl.name=N'Transactions' 
AND SCHEMA_NAME(tbl.schema_id)='dbo')) 

评论:

SQL管理工作室计算行数的方法(查看表属性、存储、行数)。非常快,但仍然是大概的行数。

方法4:

查询:

SELECT SUM (row_count) 
FROM sys.dm_db_partition_stats 
WHERE object_id=OBJECT_ID('Transactions')    
AND (index_id=0 or index_id=1); 

评论:

操作快(虽然不如方法二快),同样重要的是,可靠。

其他回答

如果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版本中使用它,因为它可能在不久的将来被删除。

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

也许有点晚,但这可能会帮助其他人的MSSQL

;WITH RecordCount AS (  SELECT      ROW_NUMBER() OVER (ORDER BY
COLUMN_NAME) AS [RowNumber]     FROM        TABLE_NAME )  SELECT
MAX(RowNumber) FROM RecordCount

PostgreSQL:

SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = 'table_name'

如果你有一个典型的表结构,其中有一个自动递增的主键列,其中的行永远不会被删除,下面的方法将是确定记录计数的最快方法,并且应该在大多数ANSI兼容的数据库中类似地工作:

SELECT TOP(1) <primarykeyfield> FROM <table> ORDER BY <primarykeyfield> DESC;

我使用的MS SQL表包含数十亿行,需要亚秒级的数据响应时间,包括记录计数。通过比较,类似的SELECT COUNT(*)将花费数分钟来处理。

我说这个问题有点晚了,但下面是你可以用MySQL做什么(就像我使用MySQL一样)。我在这里分享我的观察:

1) SELECT COUNT(*) AS TOTAL_ROWS FROM <TABLE_NAME>

结果 行数:508534 控制台输出:受影响的行:0发现的行:1警告:0一次查询的持续时间:0.125秒。 对于有大量行的表需要一些时间,但是行数非常精确。

2) SHOW TABLE STATUS or SHOW TABLE STATUS WHERE NAME="<TABLE_NAME>"

结果 行数:511235 控制台输出:受影响的行:0发现的行:1警告:0一次查询的持续时间:0.250秒 总结:行数不准确。

3) SELECT * FROM information_schema.tables WHERE table_schema = DATABASE();

结果 行数:507806 控制台输出:受影响的行:0发现的行:48警告:0查询一次的持续时间:1.701秒。 行数不准确。

我不是MySQL或数据库专家,但我发现对于非常大的表,你可以使用选项2或3,并得到一个“公平的想法”有多少行。

我需要获得这些行数,以便在UI上显示一些统计信息。通过上面的查询,我知道总行数超过了50万,所以我提出了显示“超过50万行”这样的统计信息,但没有显示确切的行数。

也许我没有真正回答OP的问题,但我在分享我在需要这样的统计数据的情况下所做的事情。在我的情况下,显示大致的行是可以接受的,所以上面的工作对我来说。