为什么information_schema.tables为行数提供了这样一个不稳定的答案?

时间:2015-10-28 05:56:43

标签: mysql information-schema

我使用MySQL 5.5遇到了一个奇怪的问题。我想收集有关表格大小的统计数据。所以,我编写了以下查询:

SELECT table_name AS name, data_length, index_length, table_rows, avg_row_length
FROM information_schema.TABLES 
WHERE table_schema = "<MySchema>"
 AND table_name in (<Table names I'm interested in>)
order by table_name;

然而,当我在几秒钟内多次运行此查询时,我注意到一些奇怪的事情。 data_length和index_length在所有查询中实际上保持相同(或者稍微改变一下,因为在客户执行脚本期间有一些写入)。

然而,table_rows每次给出一个非常不同的答案。例如,第一个查询为表A提供了大约10000行,第二个查询表示它大约有20000行,依此类推。但是,当我像这样运行查询时:

select count(*) from TableA;

它一次又一次地给我相同的结果。但是,由于某种原因,不是信息模式。数据库有什么问题?或者我可能只是误解了information_schema中table_rows的含义?

2 个答案:

答案 0 :(得分:3)

来自 INFORMATION_SCHEMA.TABLES

  

如果表位于INFORMATION_SCHEMA数据库中,则 TABLE_ROWS 列为NULL。

     

对于InnoDB表,SQL中使用的行数仅粗略估计   优化。 (如果对InnoDB表进行分区,也是如此。)

要更新此估算值,您需要使用ANALYZE TABLE(请注意,innodb_stats_persistent_sample_page上的准确度依赖于:

  

<强> innodb_stats_persistent_sample_pages

     

在估算索引列的基数和其他统计信息时要采样的索引页数,例如由ANALYZE TABLE计算的那些。增加值可以提高索引统计信息的准确性,这可以改善查询执行计划,但代价是在执行InnoDB表的ANALYZE TABLE期间增加了I / O

要获得准确计数,您需要使用COUNT(*)

答案 1 :(得分:-1)

FOR INNODB:

您应该使用information_schema.INNODB_SYS_TABLESTATS.NUM_ROWS来获取准确的表格行计数数据,而不是information_schema.TABLES.TABLE_ROWS

即获取包含行的表列表:

SELECT name 
FROM information_schema.innodb_sys_tablestats 
WHERE name LIKE ("YOUR_DB_SCHEMA_NAME%")
AND num_rows > 0;

就我而言,需要追溯性地为遗留系统编写集成测试。根据当前的代码库,使用正确的PDO交易rollback()是不可能的......

对于穷人的事务回滚,我只需选择包含数据的所有表并在运行测试之前/之后截断。这允许由于测试插入数据而清理种子数据和任何其他脏表。

FOR MyISAM:

你应该按照lad2025的说明使用information_schema.TABLES.TABLE_ROWS