50毫秒变5秒|SQL没改计划却变了,锅在统计信息采样

简介: 从一条日结 SQL 一夜之间慢了一百倍切入,拆解执行计划漂移的根因:InnoDB 统计信息靠随机采样、变更越阈值就重算、基数估不准、代价模型据此改选全表扫描。给出直方图、采样页数、重建统计等治本手段与索引提示的止血边界,并附三个避坑经验。

大家好,我是数据库小学妹👋 我踩过的坑,你别再踩。

同一句 SQL,周二跑 50 毫秒,周三跑 5 秒。SQL 我一行没改,表结构没动,数据量也没涨多少。我第一反应是有人偷偷改了数据。翻完两天的变更单和发布记录,什么都没有。后来我把两次 EXPLAIN 并排一放,才发现是数据库自己改了主意。

两天的 EXPLAIN,只差三列

其余列都一样,只有这三列变了。

-- 周二
-- type=ref  key=idx_status  rows=1200
-- 周三
-- type=ALL  key=NULL        rows=2100000

typeref 变成 ALL,说明它放弃索引改成了全表扫。key 变成 NULL,说明它一个索引都没用上。rows 从 1200 涨到 210 万,说明它以为这个条件要命中两百多万行。这张表总共才两百多万行,实际符合条件的只有一万多条。它凭什么觉得这个条件要命中几乎整张表?

它是估的,不是数的

InnoDB 不维护精确的行数,它靠采样。默认配置下,它随机抽 20 个索引页。用这 20 页的分布去推算整张表。20 页,每页 16KB,加起来 320KB。对一张几个 G 的表来说,这就是个小样本。抽样本来就会有偏差,数据一倾斜,偏差更大。status 这列,大部分行挤在同一个值上。落进采样页的比例稍微偏一点,推出来的基数就能差出好几倍。

那为什么是周三才飘,周二不飘?因为统计信息不是每次都重算。InnoDB 会盯着表的变更量。改动超过大约 10% 的行,就自动触发一次重采样。周二到周三那次日结,刚好越过了这个阈值。重采样就是再随机抽一遍页。抽的页不一样,估出来的基数也不一样。表里的数据其实没怎么变,计划却变了。

这里还有个参数值得记住。innodb_stats_persistent_sample_pages 控制采样页数,8.0 默认是 20。页数越小,两次重采样之间的波动就越大,计划也越容易飘。同一句 SQL,统计信息刷一次就换一次计划,根子就在这。

代价是这么算出来的

基数估错,为什么就要换路?因为优化器比的是代价。它手里有两套单价,存在 mysql.server_costmysql.engine_cost 里。顺序读一页和随机读一页,价差着几倍。

关键在于,回表的代价是按行数乘出来的。它估你要回表 210 万次,就按 210 万次随机读计费。而且不去重,同一页被读一百遍,它就记一百遍的钱。乘下来,代价直接爆表。

再看全表扫。它按表的总页数算钱,顺序读完,每页只读一次。这张表的数据页撑死几万页。几万对两百多万,差了几十倍,它当然选全表扫。它没做错什么。它只是拿了一个不准的估算,做了个诚实的判断。

光看那三列还不够,EXPLAIN 还有个 JSON 格式能翻出账本。

EXPLAIN FORMAT=JSON
SELECT ... FROM orders WHERE status = 3;

输出里每条 table 节点都带着 cost_info。走索引那条会给出回表行数和预估成本,全表扫那条写的是按总页数算的成本。两边的数字一对比,你就能看见它为什么选错。我第一次看到 rows_examined_per_scan 是 210 万的时候,才明白它不是抽风,是算错了。

直方图,给倾斜的列补上分布

MySQL 8.0 开始支持给单列建直方图。这个东西值得记。

-- 给倾斜的列建直方图,32 个桶
ANALYZE TABLE orders UPDATE HISTOGRAM ON status WITH 32 BUCKETS;

-- 看它记了什么
SELECT COLUMN_NAME, HISTOGRAM
FROM information_schema.column_statistics
WHERE TABLE_NAME = 'orders'\G

原来的统计信息只有一个基数,只能告诉优化器这列有 5 个不同的值。它不知道其中某一个值占了八成行。直方图不一样,它把取值范围切成若干个桶,每个桶记区间和频次分布。值集中得厉害时,桶会退化成单值桶,一个桶只装一个值,这时候估得最准。这样 WHERE status = 3 的命中行数就能贴近真实。

它也有边界。只支持单列,多列组合的倾斜管不了。唯一性很高的列建了基本没用,桶里就一个值,等于退化成基数。建完还额外占空间。所以我只给倾斜严重的状态位、类型位建。

先止血,再谈治本

当时业务还等着出报表,我先做了两件事止血。一件是重采样。

ANALYZE TABLE orders;

重采样能立刻刷新统计信息,多数情况下计划就回来了。但它只是这一刻准了,数据再变还可能再飘。另一件是索引提示。在 SQL 里加 USE INDEX 或者 FORCE INDEX,把计划强行掰回原样。它能立刻见效,代价我也写在下面。

手段 治什么 局限
ANALYZE 重建统计信息 采样数据过期 数据再变还会飘
提高采样页数 样本太小 IO 开销跟着变大
直方图 单列数据倾斜 只支持单列,高基数列无效
索引提示 立刻恢复执行计划 治标不治本,索引变更直接报错

避坑清单

大表 ANALYZE TABLE 别在高峰期跑,它会触发索引页采样。你要是把采样页数调大了,IO 压力会更明显。我们现在的做法是把它排进低峰运维窗口,跟备份错开。

FORCE INDEX 千万别当长期方案。它把一个动态的决定,写死在了 SQL 里。索引一旦改名或被删,SQL 直接报错。更麻烦的是,它会把真正的问题盖住。统计信息一直不准下去,谁都不会再去看它。

最后一条我踩得最狠。innodb_stats_persistent 这个参数如果没打开,统计信息就不落盘。重启之后它会重新采样,执行计划可能在重启后整体变样。我们有一次大版本维护之后,第二天一批 SQL 的计划全变了。查了整整一天,最后才定位到这个开关。现在它在我们的基线配置里是必须开的,也只有开了它,前面说的采样页数才管得住。

写在最后

执行计划漂移不是数据库在抽风。它是拿着一个不准的估算,做了一次诚实的决定。所以治它要分两层。

第一层是让估算更准,采样页数和直方图都在这一层。一个治样本量太小,一个治数据倾斜。第二层是让漂移能被发现,把核心 SQL 的执行计划纳入监控,计划一变就告警。第二层我们做得很晚,吃过好几次亏。往往是业务先感知到慢,我们才知道。

别用索引提示把问题压住。 压住的是症状,统计信息该不准还是不准。我现在的顺序是先 ANALYZE 看能不能恢复。恢复了就去查它为什么会飘,是数据倾斜还是采样太少,把根因解决掉。索引提示只留给那些实在来不及治、但又必须马上恢复的核心 SQL。

你遇到过执行计划莫名其妙变差吗?最后是怎么定位的?评论区聊聊。

我是数据库小学妹,帮你少走弯路少踩坑,咱们下篇见👋

相关文章
|
2天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
5027 6
|
14天前
|
人工智能
千问办公官网入口:阿里AI办公QwenWork产品页和免费网页端链接
千问办公官网含两大入口:一是网页端(qwenwork.cn),即开即用,支持浏览器直接访问;二是阿里云产品页 https://t.aliyun.com/U/JNKJuO 提供免费/付费版详情、功能介绍及使用指南。
|
14天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
|
13天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1695 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
15天前
|
缓存 人工智能 自然语言处理
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
本文是阿里云百炼平台Qwen3.8-Flash大模型的选型接入指南,作为兼顾性能与响应速度的高性价比多模态模型,它支持百万级上下文窗口、全场景多模态输入与完整智能体能力矩阵,适配编程辅助、智能体协作等核心场景。文中同步梳理了最新下调的阶梯定价、夜间4折等优惠活动,搭配OpenAI兼容流式调用示例,帮助开发者低成本快速落地高并发AI应用。
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
|
9天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
1040 1
|
15天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
2008 15
|
16天前
|
缓存 JSON API
阿里云千问Qwen3.8‑Max深度解析:核心能力、订阅计费规则、API接入配置与生产落地完整教程
Qwen3.8‑Max作为千问系列新一代MoE架构旗舰基座,总参数量达到2.4万亿,激活参数950亿,是面向复杂专业任务、长周期智能体、工程级代码开发、多模态深度解析的高阶大模型,原生支持文本、图像、视频多模态输入,最大上下文窗口达到百万Token,最大输出Token支持131072,内置深度思考推理链路,在编程、科研、法律金融专业分析、长视频文档解析、自主Agent任务等场景能力表现突出。很多开发者在项目前期直接接入该旗舰模型,却对模型能力边界、多种计费模式、订阅套餐权益、API参数配置、上下文缓存优化缺乏完整认知,出现成本失控、接口报错、长文本信息丢失、深度思考模式额外消耗大量Token等
1096 5