← 返回题目列表

MySQL 直方图和索引基数如何影响优化器选择?

中等 第 23 / 28 题 更新于 2026/07/30
MySQL优化器直方图索引基数

简化版

索引基数表示列中不同值的大致数量,基数越高,索引区分度通常越好。优化器会根据统计信息估算扫描行数和成本,再决定是否走索引、走哪个索引。直方图可以补充无索引列或数据分布不均列的统计信息,让优化器更准确理解某些值很常见、某些值很少见。统计信息过旧或分布倾斜时,优化器可能选错索引。

详细版

MySQL 优化器不是直接“知道”真实数据量,而是基于统计信息估算成本。比如 status 列只有几个值,单独索引区分度很低;而 user_id 列值很多,通常更适合过滤。问题在于真实业务数据常常倾斜,例如 status='success' 占 99%,status='failed' 占 1%,如果统计信息不准确,执行计划就可能不稳定。

直方图的作用是描述列值分布,帮助优化器做更接近真实的选择。它不是索引,不能直接加速读取,但可能让优化器少选错计划。

完整版教学

一、索引基数是什么

基数可以理解为列中不同值数量。

不同值越多,过滤能力通常越强。

性别、状态这类列基数低。

手机号、用户 id 这类列基数高。

基数是优化器估算选择率的重要依据。

二、为什么优化器会选错

优化器依赖统计信息。

统计信息可能过期。

数据分布可能严重倾斜。

查询条件组合可能和单列统计不一致。

这些都会导致估算行数偏离真实行数。

三、直方图解决什么

直方图描述列值分布。

它能让优化器知道某些值很多,某些值很少。

尤其适合没有索引但常参与过滤的列。

也适合低基数但分布极不均匀的列。

直方图不是索引,它不负责定位数据,只负责帮助优化器估算成本。

四、示例场景

SELECT *
FROM orders
WHERE status = 'failed'
  AND created_at >= '2026-07-01';

如果 failed 很少,走状态相关过滤可能更有利。

如果优化器误以为各状态平均分布,就可能选择不理想计划。

直方图能让估算更接近真实分布。

五、优化手段对比

手段作用注意点
更新统计信息刷新表和索引统计解决过期问题
直方图描述列值分布不等于索引
联合索引提供访问路径有写入和空间成本
Hint人工干预计划容易绑定当前数据分布

六、什么时候不该依赖直方图

如果查询本身需要大量回表,直方图不能消除 IO。

如果条件列非常高频过滤,索引可能更合适。

如果业务数据变化很快,直方图也可能过期。

如果 SQL 写法导致索引失效,统计信息再准也救不了。

七、误区和追问

  • 误区:基数高的索引一定会被选中。 优化器还会考虑范围、排序、回表、覆盖和成本。
  • 误区:直方图能替代索引。 直方图只改善估算,不提供数据访问路径。
  • 误区:优化器选错一定是 Bug。 很多时候是统计信息旧、数据倾斜或 SQL 条件复杂。
  • 追问:如何判断估算偏差? 对比 EXPLAIN 估算行数和实际执行扫描行数。
  • 追问:低基数字段要不要建索引? 要看分布、查询条件和组合索引设计,不能只看基数低就否定。
  • 追问:直方图适合哪些列? 常用于过滤、分布倾斜、未建索引但影响计划的列。

八、面试收束

回答时先讲优化器依赖统计信息。

再解释基数、数据倾斜和直方图。

最后补充它和索引、Hint、统计刷新之间的边界。