首页 > 数据库 >为什么MySQL的information_schema.tables字段index_length显示为0?

为什么MySQL的information_schema.tables字段index_length显示为0?

时间:2024-06-05 11:11:02浏览次数:40  
标签:information stats index length test table schema

 

为什么MySQL的information_schema.tables字段index_length显示为0?

 

测试版本为:MySQL社区版 8.0.36

 

分情况1:
innodb引擎的表是索引组织表,按照主键进行顺序存放。
则表是索引,索引是表,index_length不会有值。

如下,创建一个表,并追加主键,查看索引情况。

(root@localhost 11:02:20) [zkm](7994090)> create table test as select * from information_schema.tables;
Query OK, 691 rows affected (3.19 sec)
Records: 691  Duplicates: 0  Warnings: 0

(root@localhost 11:05:35) [zkm](7994090)> alter table test add primary key (table_schema,table_name);
Query OK, 0 rows affected (0.51 sec)
Records: 0  Duplicates: 0  Warnings: 0

(root@localhost 11:07:34) [zkm](7994090)> show indexes from test;
+-------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| test  |          0 | PRIMARY  |            1 | TABLE_SCHEMA | A         |           9 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| test  |          0 | PRIMARY  |            2 | TABLE_NAME   | A         |         691 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+-------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.02 sec)

(root@localhost 11:08:04) [zkm](7994090)> SELECT CONCAT(table_schema, '.', table_name) 'owner.table_name',
    ->        table_rows AS 'Number of Rows',
    ->        format_bytes(data_length) AS 'dataSize',
    ->        format_bytes(index_length) AS 'indexSize',
    ->        format_bytes(data_length + index_length) AS 'totalSize'
    ->   FROM information_schema.tables
    ->  WHERE table_schema = DATABASE()
    ->    AND table_name = 'test';
+------------------+----------------+------------+------------+------------+
| owner.table_name | Number of Rows | dataSize   | indexSize  | totalSize  |
+------------------+----------------+------------+------------+------------+
| zkm.test         |            691 | 128.00 KiB |    0 bytes | 128.00 KiB |
+------------------+----------------+------------+------------+------------+
1 row in set (0.00 sec)

 

 

情况2:防。

如果此时在情况1的基础上,创建一个其他字段的索引,可以看到,index_length依然值为0。

(root@localhost 16:04:29) [zkm](8036866)> create index idx_t_checksum on test(checksum);
Query OK, 0 rows affected (0.39 sec)
Records: 0  Duplicates: 0  Warnings: 0

(root@localhost 16:07:36) [zkm](8036866)> show indexes from test;
+-------+------------+----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name       | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| test  |          0 | PRIMARY        |            1 | TABLE_SCHEMA | A         |          10 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| test  |          0 | PRIMARY        |            2 | TABLE_NAME   | A         |         692 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| test  |          1 | idx_t_checksum |            1 | CHECKSUM     | A         |           1 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
+-------+------------+----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
3 rows in set (0.05 sec)

(root@localhost 16:07:39) [zkm](8036866)> SELECT CONCAT(table_schema, '.', table_name) 'owner.table_name',
    ->        table_rows AS 'Number of Rows',
    ->        format_bytes(data_length) AS 'dataSize',
    ->        format_bytes(index_length) AS 'indexSize',
    ->        format_bytes(data_length + index_length) AS 'totalSize'
    ->   FROM information_schema.tables
    ->  WHERE table_schema = DATABASE()
    ->    AND table_name = 'test';
+------------------+----------------+------------+------------+------------+
| owner.table_name | Number of Rows | dataSize   | indexSize  | totalSize  |
+------------------+----------------+------------+------------+------------+
| zkm.test         |            692 | 128.00 KiB |    0 bytes | 128.00 KiB |
+------------------+----------------+------------+------------+------------+
1 row in set (0.05 sec)

https://www.cnblogs.com/PiscesCanon/p/18232608

 

首先从百度一通,没解决问题。

然后从官网看看information_schema.tables字段index_length的解释:

对于InnoDBINDEX_LENGTH 是分配给non-clustered indexes的近似空间量(以字节为单位)。具体来说,它是non-clustered indexes大小(以页为单位)的总和乘以 InnoDB页大小。

还是没解决问题,但实际上对于information_schema.tables官网开头的介绍可以看出端倪,再回去仔细瞧瞧。

查询tables显示的是目标表的统计信息的缓存值,而这个缓存值不一定准确可能是过期的,这就是原因了。

information_schema_stats_expiry定义了缓存表统计信息多久过期,以秒为单位(默认是1天)。

对参数的说明可以直到,默认情况下,当查询这些列时,MySQL 会从 mysql.index_stats 和 mysql.table_stats 字典表中检索这些列的缓存值,这比直接从存储引擎检索统计信息更有效。如果缓存统计信息不可用或已过期,MySQL 会从存储引擎中检索最新统计信息并将其缓存在 mysql.index_stats 和 mysql.table_stats 字典表中。后续查询将检索缓存统计信息,直到缓存统计信息过期。服务器重新启动或第一次打开 mysql.index_stats 和 mysql.table_stats 表不会自动更新缓存统计信息。

要立即更新某张表在tables的缓存值,可以使用analyze table语句,而如果要绕过缓存值直接查村存储引擎兼做最新统计数据,则设置information_schema_stats_expiry=0。

更多细节看官网的说明吧。

按照官方的说法,设置information_schema_stats_expiry=0或者analyze table,都能查到值了。

不过还是遇到问题了。。。

当设置information_schema_stats_expiry=0,对于index_length的值还是0(直接给我整懵了),不过像update_time这个倒是准确了,额外提出来做个对比。如下:

(analyze table test,则没问题会更新index_langth的值,这里略了)

(root@localhost 09:49:30) [zkm](8157259)> insert into test (table_schema,table_name,create_time,TABLE_COLLATION) values ('g','g',now(),'g');
Query OK, 1 row affected (0.00 sec)

(root@localhost 09:49:31) [zkm](8157259)> commit;
Query OK, 0 rows affected (0.00 sec)

(root@localhost 09:49:38) [zkm](8157259)> SELECT INDEX_LENGTH,UPDATE_TIME from information_schema.tables WHERE TABLE_NAME = 'test';
+--------------+---------------------+
| INDEX_LENGTH | UPDATE_TIME         |
+--------------+---------------------+
|            0 | 2024-06-05 09:04:22 |
+--------------+---------------------+
1 row in set (0.01 sec)

(root@localhost 09:49:48) [zkm](8157259)> set session information_schema_stats_expiry = 0;
Query OK, 0 rows affected (0.00 sec)

(root@localhost 09:49:56) [zkm](8157259)> SELECT INDEX_LENGTH,UPDATE_TIME from information_schema.tables WHERE TABLE_NAME = 'test';
+--------------+---------------------+
| INDEX_LENGTH | UPDATE_TIME         |
+--------------+---------------------+
|            0 | 2024-06-05 09:49:31 |
+--------------+---------------------+
1 row in set (0.00 sec)

--重新设置回去,update_time时间变回去了,说明mysql.table_stats的值并没有被更新
(root@localhost 09:49:57) [zkm](8157259)> set session information_schema_stats_expiry = 86400;
Query OK, 0 rows affected (0.00 sec)

(root@localhost 09:50:05) [zkm](8157259)> SELECT INDEX_LENGTH,UPDATE_TIME from information_schema.tables WHERE TABLE_NAME = 'test';
+--------------+---------------------+
| INDEX_LENGTH | UPDATE_TIME         |
+--------------+---------------------+
|            0 | 2024-06-05 09:04:22 |
+--------------+---------------------+
1 row in set (0.01 sec)

 

 

 

在mos文档“The Data and Index Length in the TABLES Information Schema Table Are Not Updating (文档 ID 2567751.1)”也提到了跟information_schema_stats_expiry有关,,,,,,

he information in information_schema.TABLES for InnoDB tables is only updated when the index statistics for the table are updated. In MySQL 8.0, there is additionally the information_schema_stats_expiry option that defines how long time the Information Schema will cache data on its own.

This means that the DATA_LENGTH and INDEX_LENGTH columns will only be updated when there either has been enough changes to the table to trigger an automatic update, or an explicit update has been triggered through ANALYZE TABLE or similar. 

(InnoDB 表的 information_schema.TABLES 中的信息仅在表的索引统计信息更新时才会更新。在 MySQL 8.0 中,还有 information_schema_stats_expiry 选项,该选项定义信息模式将自行缓存数据的时间。

这意味着,只有当表发生足够多的更改以触发自动更新,或者通过 ANALYZE TABLE 或类似操作触发显式更新时,DATA_LENGTH 和 INDEX_LENGTH 列才会更新。)

而在mos文档“When Does InnoDB Update the Index Statistics? (文档 ID 1463718.1)”详细提到了innodb的索引统计信息的更新启动条件,可以看看潇湘隐者的:MySQL InnoDB什么时候更新索引的统计信息?,知识来源也是这个mos文档,但是中文更易读。

也就是说索引统计信息更新的情况除了“analyze table”和“optimize table(本质是触发analyze table)”外,对于持久统计信息的表,那就是当 1/10 (10%) 行发生更改时,索引统计信息将更新,限制为每次更新之间必须至少经过 10 秒。

这篇mos文档倒是没提到information_schema_stats_expiry,乱的雅痞。

另外在“Why Is the Database Size Returned by "du -ch" Different From the One From information_schema.TABLES? (文档 ID 2422575.1)”则提到:

    • Bug 19811005 - ALTER TABLE ADD INDEX DOES NOT UPDATE INDEX_LENGTH IN I_S TABLES
      Fixed in 5.6.44, 5.7.26, 8.0.16 and later.
    • Bug 22778072 - INDEX_LENGTH IS 0 (SHOW TABLE STATUS) AFTER CREATE INDEX

不过Bug链接已经无法访问,可能没有权限或者没这个Bug了,不确定。

所以也只能通过“analyze table"方式了。

 

目前觉得information_schema_stats_expiry=0不生效是Bug。

 

标签:information,stats,index,length,test,table,schema
From: https://www.cnblogs.com/PiscesCanon/p/18232608

相关文章

  • 【git commit错误】error: bad signature 0x00000000 fatal: index file corrupt原因
    解决Git错误:error:badsignature0x00000000fatal:indexfilecorrupt原因分析及解决方案在使用Git进行版本控制时,可能会遇到各种错误。其中之一是关于索引文件(通常为.git/index)损坏的错误,这会导致无法正常提交更改。基础知识Git索引:Git使用一个索引文件来跟踪工作目......
  • ubuntu 解决apt-get: Some index files failed to download. They have been ignored,
    很多博主都有编写把resolve.config文件里的conserve改为8.8.8.8,但还有一种可能是没有用最新的镜像源网址,导致找不到文件,推荐找一些最近的含有镜像源的帖子。另外就是连过外网之后导致板子和环境的网域不一样,都有可能。一般把这三种方法试了之后都是可以解决问题的。镜像源没有......
  • allure的suites(测试套)中未显示返回值参数,显示No information about test execution is
    转自大佬:https://blog.csdn.net/sbdxmnz/article/details/137016423 ExecutionNoinformationabouttestexecutionisavailable.  解决方法:添加代码,因为pytest输出文本形式测试报告时未存储响应内容#将接口响应的文本内容附加到Allure报告中allure.attach(接口响......
  • 718-Maximum length of repeated subarry
    题目描述链接:https://leetcode.com/problems/maximum-length-of-repeated-subarray/description/Giventwointegerarrays nums1 and nums2,return themaximumlengthofasubarraythatappearsin both arrays.解释:给定两个数组nums1和nums2,求两个数组的最长公......
  • css29 CSS Layout - The z-index Property
    https://www.w3schools.com/css/css_z-index.asp CSSLayout-Thez-indexProperty  Thez-indexpropertyspecifiesthestackorderofanelement.Thez-indexPropertyWhenelementsarepositioned,theycanoverlapotherelements.Thez-indexproperty......
  • 美团多场景多任务学习论文《HiNet: Novel Multi-Scenario & Multi-Task Learning with
    模型结构模型主要包含场景抽取层和任务抽取层(上图A):场景抽取层场景抽取层主要包括了场景共享专家(Scenario-sharedexpert)模块、当前场景特有专家(Scenario-specificexpert)模块以及场景感知注意力网络,通过这三部分的信息抽取,最终形成了场景层次的信息表征场景共享专家就是一......
  • mysql中key 、primary key 、unique key 与index区别
    索引被用来快速找出在一个列上用一特定值的行。没有索引,MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大,花费时间越多。如果表对于查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要考虑所有数据。如果一个表有1000行,这比......
  • 使用 LlamaIndex + Eleasticsearch ,进行 RAG 检索增强生成
    节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学.针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。合集:《大模型面试宝典》(2024版)正式发......
  • height_scale = scales[2] IndexError: index 2 is out of bounds for axis 0 with si
    1.yolov5网络层优化在yolov5训练之前最好是改一下网络层,要不会报这个错。Traceback(mostrecentcalllast): File"convertCaffe.py",line159,in<module>   convertToCaffe(graph,prototxt_path,caffemodel_path,exis_focus=True,focus_concat_name="Concat_40",......
  • error Conflict: Multiple assets emit different content to the same filename ind
    ERRORFailedtocompilewith1error20:32:04errorConflict:Multipleassetsemitdifferentcontenttothesamefilenameindex.htmlERRORinConflict:Multipleassetsemitdif......