直方图仅提升优化器对倾斜列的选择率估算精度,需同时满足“列在关键条件中、无有效索引、值分布严重倾斜”三条件才生效;必须通过元数据查询和explain前后rows对比验证是否真正起效。

直方图本身不加速查询,它只让优化器对 WHERE、JOIN 或 GROUP BY 条件中列的选择率(selectivity)估算得更准——这是执行计划变优的唯一入口。
直方图只在优化器“猜不准”时才被读取
当列满足三个条件时,直方图才可能生效:
- 该列出现在关键过滤/连接条件中(如
WHERE status = 'refunded') - 没有可用索引,或条件未命中索引前导列(例如有
INDEX(status, created_at),但查询只用WHERE created_at > '2025-01-01') - 列值分布严重倾斜(比如
status中 97% 是'active',其余 12 种状态共占 3%)
只要缺一个,EXPLAIN 的 rows 预估就不会变,直方图等于没用。常见误判包括:给主键列建直方图、对 WHERE UPPER(name) = 'JOHN' 的 name 列建、或在分区表上建了但查询没指定分区。
ANALYZE TABLE ... UPDATE HISTOGRAM 后必须验证是否真被采纳
命令执行成功 ≠ 优化器用了它。必须两步确认:
- 查元数据:
SELECT HISTOGRAM FROM information_schema.COLUMN_STATISTICS WHERE TABLE_NAME = 't' AND COLUMN_NAME = 'status';—— 返回非空 JSON 才算写入成功 - 比预估:
EXPLAIN FORMAT=JSON SELECT * FROM t WHERE status = 'cancelled';建直方图前后对比输出中"rows"字段,从 15000 → 220 这类量级变化才算真正起效
注意:如果查询里写了函数包装(如 WHERE DATE(created_at) = '2025-06-01'),优化器根本不会关联到 created_at 的直方图,因为统计对象是表达式结果,不是原始列。
选错 TYPE 或桶数,会让优化器更迷糊
SINGLETON 和 EQ_HEIGHT 不是默认随便选的,类型错直接导致精度崩塌或解析拖慢:
- 低基数离散列(如枚举
status、order_type)→ 必须用SINGLETON,桶数设为唯一值数量 ±20%(18 种状态就WITH 22 BUCKETS);若误用EQ_HEIGHT,会把所有值强行塞进等频区间,丢失真实频次 - 高基数连续列(如
created_at、user_id)→ 用EQ_HEIGHT,桶数控制在 100–256;超过 1000 会导致information_schema.COLUMN_STATISTICS表体积激增,且每次查询解析都要多花几毫秒加载元数据 - 字符串列平均长度 > 200 字节时,直接建直方图可能报
ER_TOO_LONG_STRING;可临时截断:ANALYZE TABLE t UPDATE HISTOGRAM ON SUBSTRING(status, 1, 100) WITH 20 BUCKETS;,但要注意精度损失
最常被忽略的一点:直方图不是一劳永逸的。数据持续写入后,分布会漂移;尤其在低峰期批量导入新状态值后,旧直方图反而可能误导优化器。更新频率取决于业务变更节奏,不能只依赖首次创建。











