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

news/2025/3/18 12:52:43/文章来源:https://www.cnblogs.com/PiscesCanon/p/18232608

 

为什么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。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/720226.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

etcd-v3.5.9源代码分析

Github上下载etcdv3.5.9源代码,包含server和client两部分。 先放ETCDv3 读写流程图镇楼读流程写流程 Etcd Server server->etcdmain->main.go:Main():startEtcdOrProxyV2() ->etcd.go:startEtcd()->StartEtcd()->etcdserver目录下server.go:NewServer() 初始化…

【长亭雷池WAF】介绍及“动态防护”功能深度体验

一、介绍 什么是雷池 雷池(SafeLine)是长亭科技耗时近 10 年倾情打造的 WAF,核心检测能力由智能语义分析算法驱动。 Slogan: 不让黑客越雷池半步。 什么是 WAF WAF 是 Web Application Firewall 的缩写,也被称为 Web 应用防火墙。 区别于传统防火墙,WAF 工作在应用层,对基…

Goland无法Debug

起因 今天用goland,Debug代码出现如下报错 其原因是因为正在使用的Delve试调器版本太旧,无法兼容当前的Go语言版本1.22.1 Delve是Go语言的一个调试工具,用于提供源码级别的调试功能 Go语言每隔一段时间会发布新版本,而相应的调试器Delve也可能会更新以提供新的特性或修复已…

2.6倍!WhaleTunnel 客户POC实景对弈DataX

作为阿里早期的开源产品,DataX是一款非常优秀的数据集成工具,普遍被用于多个数据源之间的批量同步,包括类似Apache DolphinScheduler的Task类型也对DataX进行了适配和增强,可以直接在DolphinScheduler里面利用通用的数据源调用DataX进行数据批量同步。 作为DolphinSchedule…

App_Code.dll没有生成问题

场景:VS2019需要生成App_Code.dll,用来更新网站接口,但是【发布/重新生成】网站后,Bin目录里头都没有找到这个App_Code.dll。 解决: 发布的时候勾选一下【在发布前删除所有现有文件】和【在发布期间预编译】即可

P4003 [清华集训 2017] 无限之环 解题报告

oj:https://gxyzoj.com/d/gxyznoi/p/P93 它要判断什么时候不漏水,就是需要建一种图,使得原图的最大流是答案 因为是网格图,考虑黑白染色,可以将\((i+j)\)对2取模的结果作为颜色,将所有颜色为1的点向源点连边,颜色为0的点向汇点连边 接下来考虑如何判断是否漏水,因为有四…

一文搞懂5种内存溢出案例,内含完整源码

在开发中需要尽量避免出现内存溢出,导致程序出现异常。本文分享自华为云社区《10分钟搞懂各种内存溢出案例!!(含完整源码,建议收藏)》,作者:冰 河。 作为程序员,多多少少都会遇到一些内存溢出的场景,如果你还没遇到,说明你工作的年限可能比较短,或者你根本就是个假…

SARscape5.7中DS-InSAR:E-PS操作说明

PS-InSAR方法测量PS点的形变,SBAS-InSAR方法测量分布式散射体DS(Distributed Scatters)的形变。随着技术的发展,在这一领域取得了许多研究进展,SARscape5.7版本开始,提供了能够同时提取PS和DS测量值的新方法,即增强型永久散射体(E-PS)和增强型短基线(E-SBAS)。 E-PS…

揭秘PW1558A:集成电源管理的6A双向限流过压保护IC

描述PW1558A 是一款先进的 28V 6A 额定双向负载开关, 提供过载、 短路、 输入电压浪涌、 过大冲击电流和过热保护, 为系统供电。 内置的 24mΩ超低 RDS(ON)电源开关有助于减少正常操作期间的功率损耗。 该设备具有两个输入/输出端口 VBUS1 和 VBUS2, 其绝对 MAX 大额定值为 …

物理隔离条件下文件交换的防泄密U盘,企业该如何选择?

对于网络安全要求高的企业和单位,往往采用物理隔离的方式进行网络建设,如政府单位、军工、科研所、航空航天企业、以及部分金融机构、医疗单位、电力企业、生物制药实验室等。但物理隔离后,仍然存在着隔离网间的数据交换需求,此时,仅能借助物理工具的方式进行文件交换,而…

第三届机器人、人工智能与信息工程国际学术会议(RAIIE 2024)

2024年第二届机器人、人工智能与信息工程国际学术会议(RAIIE 2024)将于2024年7月5-7日在新加坡举行。【ACM独立出版/Fellow大咖云集】2024年第二届机器人、人工智能与信息工程国际学术会议(RAIIE 2024) 2024 3rd International Symposium on Robotics, Artificial Intellig…