MySQL-使用count(*)和information_schema.tables进行行计数之间的区别


16

我想要一种快速的方法来计算表中有几百万行的行数。我在Stack Overflow上找到了“ MySQL:最快的行数计数方法 ”一文,它看起来可以解决我的问题。Bayuah提供了以下答案:

SELECT
    table_rows "Rows Count"
FROM
    information_schema.tables
WHERE
    table_name="Table_Name"
AND
    table_schema="Database_Name";

我喜欢它,因为它看起来像查找而不是扫描,因此它应该很快,但是我决定对它进行测试

SELECT COUNT(*) FROM table 

看看有多少性能差异。

不幸的是,我得到了如下所示的不同答案

在此处输入图片说明

为什么答案相差约200万行?我猜执行全表扫描的查询是更准确的数字,但是有没有一种方法可以不必运行此慢查询就可以获取正确的数字?


我跑了ANALYZE TABLE data_302,完成了0.05秒。当我再次运行查询时,我现在得到了34384599行的更接近的结果,但是它仍然select count(*)与34906061行的数字不同。分析表是否立即返回并在后台处理?我觉得值得一提的是,这是一个测试数据库,目前尚未写入。

没有人会在乎是否只是告诉某人一个表有多大的情况,但是我想将行数传递给一些代码,该代码将使用该数字来创建一个“大小相等”的异步查询来查询数据库并行地,类似于Alexander Rubin通过并行查询执行提高慢查询性能中所示的方法。照原样,我将获得最高的ID,SELECT id from table_name order by id DESC limit 1并希望我的表不要过于分散。

Answers:


23

有多种方法可以对表中的行进行“计数”。最佳选择取决于要求(计数的准确性,执行的频率,是否需要整个表的计数或带有变量wheregroup by子句的计数等)

  • a)正常方式。一下。

    select count(*) as table_rows from table_name ; 

    准确度:查询运行时100%的准确计数。
    效率:不适用于大桌子。(因为MyISAM表的速度非常快,但是现在没有人使用MyISAM,因为它比InnoDB有很多缺点。“惊人的快速”也仅在计算整个MyISAM表的行时适用-如果查询WHERE有条件,仍然必须扫描表或索引。)
    对于InnoDB表,它取决于表的大小,因为引擎必须扫描整个表或整个索引以获取准确的计数。桌子越大,它就越慢。

  • b)使用SQL_CALC_FOUND_ROWSFOUND_ROWS()。如果我们还需要少量的行(可以更改LIMIT),则可以代替以前的方法使用。我已经看到它用于分页(获取一些行,同时知道有多少个int总数并计算pgeg的数量)。

    select sql_calc_found_rows * from table_name limit 0 ; 
    select found_rows() as table_rows ;

    精度:与以前相同。
    效率:与以前相同。

  • c)使用information_schema表格作为链接的问题:

    select  table_rows
    from    information_schema.tables
    where   table_schema = 'database_name'
      and   table_name = 'table_name' ;

    精度:仅是近似值。如果该表是频繁插入和删除的目标,则结果可能与实际计数相差甚远。通过ANALYZE TABLE更频繁地运行可以改善这一点。
    效率:很好,它根本不会碰到桌子。

  • d)将计数存储在数据库中(在另一个“ counter”表中),并在表具有插入,删除或截断的每一次时更新该值(这可以通过触发器或通过修改插入和删除过程来实现) 。
    当然,这将在每个插入和删除操作中增加额外的负担,但将提供准确的计数。

    准确度:100%准确计数。
    效率:很好,只需要从另一个表中读取一行。
    但是,这给数据库带来了额外的负担。

  • e)将计数存储(缓存)在应用程序层中,并使用第一种方法(或先前方法的组合)。示例:每10分钟运行一次精确计数查询。在两次计数之间的平均时间中,使用缓存的值。

    精度:近似值,但在正常情况下不太差(除非添加或删除了数千行)。
    效率:很好,价值永远存在。


1

对于INNODB您想要information_schema.INNODB_SYS_TABLESTATS.NUM_ROWS准确的表行计数数据,而不是information_schema.TABLES.TABLE_ROWS

我在此处发布了更多详细信息:https : //stackoverflow.com/questions/33383877/why-does-information-schema-tables-give-such-an-unstable-answer-for-number-of-ro/49184843#49184843


1
错误信息...... “对于InnoDB你想准确的表行information_schema.INNODB_SYS_TABLESTATS.NUM_ROWS:” 手册明确表示,估计NUM_ROWS科拉姆
雷蒙德Nijland
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.