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

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

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

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


当前回答

在SQL server 2016中,我可以检查表属性,然后选择“存储”选项卡-这给了我行数,表使用的磁盘空间,使用的索引空间等。

其他回答

这并不是一个与dbms无关的解决方案,但至少您的客户端代码看不到区别……

创建另一个只有一行和一个整数字段N1的表T,并创建INSERT TRIGGER,只执行:

UPDATE T SET N = N + 1

还可以创建一个DELETE TRIGGER来执行:

UPDATE T SET N = N - 1

一个称职的DBMS将保证2以上操作的原子性,并且N将始终包含准确的行数,然后超级快速地简单地获得:

SELECT N FROM T

虽然触发器是特定于DBMS的,但从T中选择不是,并且您的客户端代码不需要为每个受支持的DBMS更改。

但是,如果表是INSERT或DELETE密集型的,这可能会有一些可伸缩性问题,特别是如果在INSERT/DELETE之后没有立即提交。


1这些名称只是占位符——在生产中使用更有意义的名称。

也就是说,N不能通过读和写N之间的并发事务来改变,只要读和写都是在一条SQL语句中完成的。

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

SELECT COUNT_BIG(*) FROM TABLENAME;

到目前为止,MySQL上最快的方法是:

SHOW TABLE STATUS;

您将立即获得所有表的行数(即总数)以及大量额外信息(如果需要的话)。

为我准备了一张很大的桌子,

SELECT COUNT(1) FROM TableLarge 

花了37秒

SELECT COUNT_BIG(1) FROM TableLarge

只需要4秒钟。

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

这取决于数据库。有些方法可以加速计数,例如通过跟踪索引中的行是活的还是死的,从而允许只扫描索引来提取行数。其他的则不是,因此需要访问整个表并逐个计算活动行。对于一张大桌子来说,这两种方式都很慢。

请注意,您通常可以通过使用查询优化工具、表统计信息等提取一个良好的估计。例如,在PostgreSQL的例子中,你可以从你的表中解析explain count(*)的输出,并得到一个相当好的行数估计。这就引出了你的第二个问题。

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

严重吗?:-)你真的是指一个有数十亿行的表的精确计数吗?你真的确定吗?: -)

如果您真的这样做了,您可以使用触发器跟踪总数,但如果这样做了,请注意并发性和死锁。