直方图仅在无索引、值分布严重倾斜且WHERE条件未被函数包裹时提升基数估算精度;需满足三条件:列出现在过滤/连接/分组中、EXPLAIN预估与实际行数相差超10倍、值分布头一个占比>85%。

直方图不会让非索引列突然变快,它只在优化器对 WHERE 条件中该列的选择率估算严重失准时起作用——前提是这列既没索引,又分布极不均匀,且查询条件没被函数包裹。
哪些非索引列值得建直方图?
别给所有字段都加,只盯住三类信号同时出现的列:
- 出现在
WHERE、JOIN ON或GROUP BY中,但该列上没有索引(或虽有复合索引,却未命中前导列) -
EXPLAIN FORMAT=JSON显示预估rows和实际扫描行数相差超 10 倍(比如预估 5 行,SELECT COUNT(*)实际返回 8 万) - 值分布明显倾斜:用
SELECT status, COUNT(*) FROM orders GROUP BY status ORDER BY COUNT(*) DESC LIMIT 5;查看,若头一个值占比 > 85%,其余十几个状态加起来才占 15%,就符合“严重不均”
ANALYZE TABLE UPDATE HISTOGRAM 的参数怎么选?
桶数和类型错一个,直方图就可能误导优化器:
- 低基数离散列(如
status、order_type)用SINGLETON类型:每个唯一值单独一桶,精度高;桶数设为实际唯一值数量 ±20%,例如 17 种状态,建 20 桶足够 - 高基数连续列(如
created_at、amount)用EQ_HEIGHT(默认),桶数控制在 100–256;超过 1000 会拖慢 SQL 解析,且information_schema.COLUMN_STATISTICS表体积暴涨 - 字符串列平均长度 > 200 字节时,
ANALYZE TABLE可能报ER_TOO_LONG_STRING;先用SUBSTRING(status, 1, 100)截断再建,但会损失部分精度
建完怎么确认它真被用了?
命令执行成功 ≠ 优化器采纳了它,必须验证两件事:
- 查元数据:
SELECT HISTOGRAM FROM information_schema.COLUMN_STATISTICS WHERE TABLE_NAME = 'orders' AND COLUMN_NAME = 'status';—— 返回非空 JSON 才算写入成功 - 比预估变化:
EXPLAIN FORMAT=JSON SELECT * FROM orders WHERE status = 'cancelled';建直方图前后对比"rows"字段;从 12000 → 380 这种量级变化才算生效 - 注意失效场景:只要查询里写了
WHERE UPPER(status) = 'CANCELLED'或WHERE status LIKE '%ed',直方图就完全不参与估算——优化器看到的是函数输出,不是原始列值
直方图真正难的地方不在创建,而在判断“它是否被需要”:你得先确认是选择率估算不准导致计划错误,而不是索引缺失、统计过期或查询写法本身有问题。一旦误判,建了也白建,还可能干扰后续调优节奏。


















