当前位置: 首页
业界动态
MySQL 导入数据后导致 SQL 性能下降

MySQL 导入数据后导致 SQL 性能下降

热心网友 时间:2026-04-15
转载

一、被关闭的自动统计数据收集

先来聊聊MySQL 8.0的统计信息机制。默认情况下,它启用了持久化统计(innodb_stats_persistent=ON)。这意味着表的行数、索引大小这些关键信息,不仅会放在内存里(比如table->stat_n_rows),还会被固化到mysql.innodb_table_statsmysql.innodb_index_stats这两张系统表中。正常情况下,内存和表里的数据是同步的:先改内存,再落盘;重启后,再用表里的数据来初始化内存。

但这里有个暗坑:mysqldump操作可能会打破这种同步,甚至损坏系统表中的统计信息。

通常,当表的数据修改量超过当前统计行数的十分之一时,InnoDB会触发后台线程自动重新收集统计信息。然而,在特定场景下,MySQL会通过执行/*!50606 SET GLOBAL INNODB_STATS_AUTO_RECALC=OFF */关闭这个自动收集功能。这样一来,导入数据时,无论插入多少行,都不会触发统计更新。

那么,什么场景会触发这个“关闭”操作呢?主要就两点:

  • 导出的数据库包含了mysql系统库。
  • 导出时使用了--all-databases参数(这是主要原因)。

因为--all-databases必然会包含存放统计信息的mysql.innodb_table_statsmysql.innodb_index_stats表。

MySQL源码中有一个名为is_innodb_stats_tables_included的函数,正是用来定义和判断这种行为的。为了验证,我们借助了一些代码分析工具,输入提示词:“请帮我找到is_innodb_stats_tables_included函数,并且分析其调用方式和作用”。结果很明确,如下图所示(在trae auto model模式下分析所得)。未来或许可以考虑用更智能的Agent来辅助代码分析,这也不失为一种高效的方法。

\

而问题的根源,恰恰就在这里。正是这个机制,导致了统计信息的丢失。我们接着往下分析。

二、统计信息丢失

统计信息丢失发生在两个层面:内存中的信息和持久化到表中的信息。它们双双“失灵”了。

第一,内存信息失效。虽然导入的SQL文件里包含了innodb_table_stats表的旧数据,但SQL语句执行时,优化器依赖的是table->stat_n_rows这个内存值。由于前面提到的自动收集功能被关闭了,这个内存值在数据导入过程中得不到更新。通过调试器(gdb)可以看到,prebuilt->table->stat_n_rows的值变成了0。

第二,持久化信息被覆盖。整个导入过程可以拆解为:先DROP TABLE,再CREATE TABLE,然后INSERT数据。问题出在CREATE TABLE这一步——它会覆盖innodb_table_stats表中对应表的现有记录。于是,持久化的统计信息在表刚重建完时就被清零了。紧接着,虽然插入了大量数据,但因为自动收集被关闭,系统不会去重新计算。最终结果就是:数据导完了,但innodb_table_stats表里却留下了大量值为0的记录,统计信息完全缺失。

三、测试

口说无凭,我们实际测试一下。分别在MySQL 8.0.23和8.0.41版本中进行,结果一致。重点关注测试库mytest的统计信息变化。

导入前,统计信息是正常的:

mysql> desc select count(*) from mytest ;
+----+-------------+--------+------------+-------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table  | partitions | type  | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------+------------+-------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | mytest | NULL       | index | NULL          | id   | 5       | NULL | 65920 |   100.00 | Using index |
+----+-------------+--------+------------+-------+---------------+------+---------+------+-------+----------+-------------+
1 row inset, 1 warning (0.00 sec)

(gdb) p prebuilt->table->stat_n_rows
$3 = 65920

mysql> select * from mysql.innodb_table_stats;
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name    | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
...| stattest      | mytest        | 2025-06-06 15:22:09 |  65920 |                  161 |                       97 |...
+---------------+---------------+---------------------+--------+----------------------+--------------------------+

可以看到,内存值(65920)和持久化表中的值(65920)是同步的。

导入后,问题出现了:

mysql> desc select count(*) from mytest ;
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table  | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | mytest | NULL       | index | NULL          | id   | 5       | NULL |    1 |   100.00 | Using index |
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+-------------+
1 row inset, 1 warning (0.00 sec)

(gdb) p prebuilt->table->stat_n_rows
$4 = 0

mysql> select * from mysql.innodb_table_stats;
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name    | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
...| stattest      | mytest        | 2025-06-06 07:00:06 |      0 |                    1 |                        1 |      ...

执行计划估算的行数变成了1(实际应为65920),内存统计值变成了0,持久化表中的n_rows也变成了0。统计信息彻底丢失了。

四、bug和建议

这个问题的潜在影响面其实挺广的,值得警惕。MySQL官方已将其确认为一个Bug,编号为:https://bugs.mysql.com/bug.php?id=98178。受影响的版本包括5.6、5.7和8.0系列。

那么,如何规避和解决呢?这里有几个建议:

A. 预防措施: 导出数据时,尽量避免使用--all-databases参数。只导出你真正需要的业务数据库,从根本上避免触发这个机制。

B. 事后检查: 数据导入新库后,务必检查mysql.innodb_table_statsmysql.innodb_index_stats这两张表。如果发现大量表的统计行数(n_rows)为0或异常小,可以考虑重启一次数据库实例。重启后,确认参数innodb_stats_auto_recalc是否为ON

C. 补救方案: 如果不幸已经中招,数据导入后出现了慢查询,最直接有效的办法就是立即手动触发全库的统计信息收集。执行命令:ANALYZE TABLE 表名; 对于受影响的表逐一处理,或者编写脚本批量处理。

来源:https://www.51cto.com/article/840211.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
小米集团辟谣官微上线,定位官方辟谣平台

小米集团辟谣官微上线,定位官方辟谣平台

小米辟谣官微6月30日正式上线,作为集团官方辟谣阵地,用户可查询辟谣声明、反馈谣言线索。账号将主动澄清网络谣言,维护合法商誉,并致力于打造权威辟谣通道,保障公众知情权与合法权益。

时间:2026-07-02 11:22
小米官方辟谣账号上线持续维护合法商誉

小米官方辟谣账号上线持续维护合法商誉

6月30日,小米集团的一则动态引发热议:小米辟谣官方账号,正式上线了。简单来说,小米这次将澄清谣言的工作直接推到了前台——在中央网信办违法和不良信息举报中心的指导下,小米辟谣的全新阵地宣告成立。 目前,这个辟谣账号已在微博开通。用户可以通过它核实与查阅小米官方的辟谣声明,也可以反馈任何涉及小米的谣言

时间:2026-07-02 11:22
特斯拉Cybercab无驾舱量产车在奥斯汀启动L4级公开道路测试

特斯拉Cybercab无驾舱量产车在奥斯汀启动L4级公开道路测试

特斯拉Cybercab量产车在奥斯汀启动L4级公开测试,彻底取消方向盘等物理控制装置。安全监督员仅观察不干预。车辆专为Robotaxi设计,搭载HW4 0与FSDV14 3 3系统,续航672公里,支持无线充电,实现全程独立驾驶。

时间:2026-07-02 11:22
鸿蒙智行回应问界M5车内异味系第三方配件所致

鸿蒙智行回应问界M5车内异味系第三方配件所致

6月30日,针对近期网络热议的“问界M5车内异味”事件,鸿蒙智行官方小助手在社区帖子下方发布了正式回应。官方表示,已对刘先生的这辆车进行了全面检测排查。工作人员上门核查后发现,涉事车辆内部加装了大量第三方配件,包括非原厂皮质、塑胶收纳摆件、脚托、抱枕、车衣等。在拆除所有加装配件后,工作人员严格依照国

时间:2026-07-02 11:22
闫闯直言20万买电车选400V太愚蠢

闫闯直言20万买电车选400V太愚蠢

2026年6月30日,微博上一则关于电动汽车高压平台技术路线的争论迅速引爆热搜。坐拥超过475万粉丝的汽车领域博主闫闯,在归还体验了4天的理想i6时,专门花费6分多钟把电量充至满格,并掷地有声地留下一句:“一点不比加油慢。”随后他补充道:“还是那句话,都这时代了,20万+电车还买400V的绝对愚蠢。

时间:2026-07-02 11:22
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜