为什么innodb的SHOW TABLE STATUS如此不可靠?

时间:2011-12-24 12:02:34

标签: mysql innodb

我知道你不应该依赖InnoDB的SHOW TABLE STATUS返回的值。 特别是行数和平均数据长度。

但我想也许这是在某个时刻采取的准确值,然后innodb只会在ANALYZE表或其他偶发事件中刷新它。

相反,我看到的是我可以在5秒钟内在同一个桌面上运行SHOW TABLE STATUS 5次,并且每次只获得完全不同的数字(尽管表中没有任何插入/删除活动)

这些价​​值实际上来自哪里?它们在innodb中只是腐败吗?

2 个答案:

答案 0 :(得分:23)

官方MySQL 5.1 documentation承认InnoDB没有提供SHOW TABLE STATUS的准确统计数据。虽然MYISAM表专门保留元数据的内部缓存,例如行数等,但InnoDB引擎将表数据和索引存储在* / var / lib / mysql / ibdata **

InnoDB没有权宜的索引文件,可以快速查询行号。

SHOW TABLE STATUS报告不一致的表行数,因为InnoDB通过对表数据的范围进行采样(在* / var / lib / mysql / ibdata **中)动态估计'行'值,然后推断出大致的行数。因此,当使用SHOW TABLE STATUS时,InnoDB文档确认行数不准确率高达50%

MySQL文档建议使用MySQL查询缓存来获得一致的行号查询,但文档未指定如何。关于如何做到这一点的简洁解释如下。

首先,检查是否启用了查询缓存:

mysql> SHOW VARIABLES LIKE 'have_query_cache';

如果 has_query_cache 的值为 NO ,则通过将以下行添加到 /etc/my.cnf 然后启用查询缓存重启mysqld。

have_query_cache=1    # added 2017 08 24 wh
query_cache_size  = 1048576
query_cache_type  = 1
query_cache_limit = 1048576

(有关详细信息,请参阅http://dev.mysql.com/doc/refman/5.1/en/query-cache.html

使用

查询缓存的内容
mysql> SHOW STATUS LIKE 'Qcache%';

现在在SQL_CALC_FOUND_ROWS查询中使用SELECT语句:

SELECT SQL_CALC_FOUND_ROWS COUNT(*) FROM my_innodb_table

SQL_CALC_FOUND_ROWS将尝试从缓存中读取,如果找不到此查询,则对指定的表执行查询,然后将表行数提交到查询缓存。上述查询的其他执行(或其他'cachable'SELECT语句 - 见下文)将查询缓存并返回正确的结果。

后续'cachable' SELECT queries - 即使他们LIMIT结果 - 将查询查询缓存并允许您获取(仅一次性)带有

的总表行号
SELECT FOUND_ROWS();

返回先前缓存的查询的正确表行总数。

答案 1 :(得分:4)

不保持准确统计数据的原因,包括表中的行数,是InnoDB用于提供交易的行的多版本化。什么是实际的行数实际上取决于事务的隔离级别(因为未提交的事务可能已经删除或插入了记录),并且不同的事务可以在不同的隔离级别运行,这意味着“有多少记录存在” '只有在没有正在运行的交易时才可以正确回答'。因此,保持行或数据长度的计数器几乎是不可能的。

详细了解InnoDB restrictions