直方图仅提升优化器对WHERE条件过滤比例(filtered)的估算精度,不改变物理扫描方式,故type: ALL仍存在;它不影响访问类型,只优化行数预估和执行计划选择。

直方图不能让无索引列跳过全表扫描,它只提升优化器对 WHERE 条件过滤比例(filtered)的估算精度——这个值变了,执行计划才可能跟着变;否则 type: ALL 会一直存在。
为什么加了直方图,EXPLAIN 还是 type: ALL
这是最常被误解的点。type: ALL 表示访问方式没变,和直方图无关;直方图只影响优化器内部的行数预估(rows)和过滤比例(filtered),不改变物理扫描逻辑。常见绕过直方图的情况包括:
-
WHERE UPPER(status) = 'ACTIVE':函数包裹后,优化器看到的是表达式结果,不是原始列,直方图失效 - 字段类型为
JSON、GEOMETRY或压缩的TEXT:MySQL 当前版本不支持为其建直方图,语句静默跳过 - 查询涉及分区表,但条件未精确匹配分区键(如按
region分区,却查WHERE created_at > '2025-01-01'):直方图元数据不会加载 - 建完直方图没执行
ANALYZE TABLE t;:优化器默认不自动重载,必须显式触发统计刷新
怎么选对 TYPE 和 BUCKETS
类型和桶数选错,直方图反而会误导优化器。关键看列值分布特征,不是凭感觉:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 低基数离散值(如
status、order_type、布尔字段)→ 必须用SINGLETON类型,桶数设为唯一值数量 ±20%。例如 12 种状态,写WITH 14 BUCKETS TYPE SINGLETON - 高基数连续值(如
created_at、user_id、金额)→ 用EQ_HEIGHT(MySQL 默认),桶数控制在 100–256。超过 1000 会拖慢查询解析,且information_schema.COLUMN_STATISTICS表体积激增 - 字符串列平均长度 > 200 字节时,直接建直方图可能报
ER_TOO_LONG_STRING;可临时截断:ANALYZE TABLE orders UPDATE HISTOGRAM ON SUBSTRING(status, 1, 100) WITH 20 BUCKETS,但要注意精度损失
如何验证直方图是否真正起作用
不能只看 Query OK,得查两处真实证据:
- 查元数据是否存在:
SELECT HISTOGRAM FROM information_schema.COLUMN_STATISTICS WHERE TABLE_SCHEMA = 'db' AND TABLE_NAME = 'orders' AND COLUMN_NAME = 'status'—— 返回非空 JSON 才算落地成功 - 对比
EXPLAIN FORMAT=JSON输出中的"filtered"字段:对低频值(如WHERE status = 'failed')执行前后对比,若从10.00→0.37,说明优化器已采纳 - 注意观察
"rows"是否同步变化:如果filtered变了但rows没变,大概率是没触发统计重载,需补一次ANALYZE TABLE orders
直方图生效的前提非常具体:列无索引、条件不包函数、数据严重倾斜、且优化器真需要它做选择率估算。漏掉任一环,就只是往 COLUMN_STATISTICS 里写了一段 JSON 而已。


















