当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 直方图统计怎样帮助没有索引的过滤条件

MySQL 直方图统计怎样帮助没有索引的过滤条件

来源:17golang原创 2026-11-14 03:12:47 0浏览 收藏

没有索引的列并不等于优化器只能“猜”。MySQL 可以为列值分布建立直方图,让优化器知道某个过滤条件大约会留下多少行,从而改进没有单列索引时的选择性估算。不过,直方图是统计信息,不是索引:它不会直接定位数据,也不会保证执行计划一定更快。

直方图最适合帮助 MySQL 认识非索引列的分布。先生成统计,再从 INFORMATION_SCHEMA.COLUMN_STATISTICS 查看状态,最后用 EXPLAIN 对照估算;如果数据分布已经变化,就重建或删除这份统计。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/

先区分索引路径和分布统计

假设订单表中的 status 没有单列索引,查询却经常按状态过滤:

-- 这个查询关注 status 的过滤选择性,而不是展示真实运行结果
SELECT id, user_id, created_at
FROM orders
WHERE status = '待处理';

没有索引时,优化器仍然需要估算“待处理”大约占全表多少比例。估算太小,可能低估扫描或后续连接成本;估算太大,也可能放弃一个本来合适的连接顺序。直方图把列值的分布压缩成若干桶,提供比均匀分布假设更具体的统计依据。

它和索引的职责不同:

对象解决的问题代价与边界
索引快速定位或有序访问符合条件的记录写入时维护索引,增加存储和维护成本
直方图描述列值分布,帮助估算过滤比例按需生成,数据变化后可能逐渐过期
EXPLAIN查看优化器选择与估算结果只反映当前优化器判断,不等同于实际耗时
MySQL 非索引列值分布通过直方图帮助优化器估算过滤选择性的结构说明图
图1:非索引列、直方图桶和过滤估算之间的关系说明图,属于原创静态结构图,不是截图或运行证据。

为非索引列生成直方图

MySQL 使用 ANALYZE TABLE 管理直方图。最小写法是指定表和列;如果不指定桶数量,服务器使用默认值。桶数量可以在 1 到 1024 之间选择,数量越多不代表估算一定越准,仍要结合列的分布和统计维护成本。

-- 为 status 列生成直方图,帮助优化器认识状态值分布
ANALYZE TABLE orders
UPDATE HISTOGRAM ON status;

-- 分布更复杂时可以显式指定桶数量
ANALYZE TABLE orders
UPDATE HISTOGRAM ON status WITH 32 BUCKETS;

直方图生成会读取用户数据;如果可用内存不足以完整读取,MySQL 可能采用采样。生成后可以从直方图 JSON 中查看 sampling-rate,它反映生成统计时读取数据的比例。采样率较低时,不要把一次估算当成永远准确的结论。

对于 MySQL 8.4,还可以在生成时指定 AUTO UPDATE。不指定时默认是 MANUAL UPDATE,后续需要显式维护;自动更新则会在相关的 ANALYZE TABLE 或 InnoDB 持久统计重新计算时更新直方图。

-- 让后续表统计刷新时一并更新该列直方图
ANALYZE TABLE orders
UPDATE HISTOGRAM ON status WITH 32 BUCKETS AUTO UPDATE;

-- 明确回到手动维护,避免把更新责任交给自动统计过程
ANALYZE TABLE orders
UPDATE HISTOGRAM ON status WITH 32 BUCKETS MANUAL UPDATE;

从 COLUMN_STATISTICS 读取状态

直方图不需要直接查询数据字典内部表,使用 INFORMATION_SCHEMA.COLUMN_STATISTICS 查看公开视图即可。重点不是只看有没有记录,而是看统计对应的列、桶数量、采样率和更新模式。

-- 查看 orders.status 当前保存的直方图 JSON
SELECT
    SCHEMA_NAME,
    TABLE_NAME,
    COLUMN_NAME,
    HISTOGRAM
FROM INFORMATION_SCHEMA.COLUMN_STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = 'orders'
  AND COLUMN_NAME = 'status';

JSON 中常见的判断点包括 histogram-type、number-of-buckets-specified、sampling-rate、last-updated 和 auto-update。例如,更新时间很旧而业务数据近期发生了大规模状态迁移,就应该把“估算不准”列入排查,而不是先修改 SQL。

直方图主要用于非索引列。如果列已经有合适的索引,优化器可能通过范围优化或索引探测得到更直接的估算,此时不一定采用直方图。直方图存在,并不表示每条查询都会使用它。

用 EXPLAIN 对照过滤估算

可以用 EXPLAIN 查看查询计划中的 rows 与 filtered。下面的语句只展示应该观察的字段,不把示例数字当成真实执行输出:

-- 观察优化器对扫描行数和过滤比例的估算
EXPLAIN
SELECT id, user_id, created_at
FROM orders
WHERE status = '待处理';

filtered 可以理解为当前访问路径下预计通过条件的百分比。比如直方图反映“待处理”约占较小比例时,估算就不应继续使用均匀分布的直觉数字。真正对比时,应在相近统计状态下记录计划,再生成或重建直方图后重新查看。

但要注意两个边界。第一,EXPLAIN 里的估算改善不等于执行时间一定下降;如果计划本来就受其他条件、连接顺序或排序成本主导,直方图的帮助可能很小。第二,优化器更偏好适用的范围优化估算,适用时不会优先依赖直方图。判断重点是估算是否更贴近数据,而不是强行让计划发生变化。

处理过期与不适用边界

直方图只在生成或更新时读取数据,普通写入不会让它即时同步。因此,下面几种场景需要重新考虑:

  • 值分布改变:例如大量订单从“新建”迁移到“完成”,旧桶已经不能代表当前比例,应重新执行 UPDATE HISTOGRAM。
  • 统计成本过高:如果某列查询收益不明显,或者维护产生的分析成本超过收益,可以删除直方图。
  • 列本身不合适:MySQL 不为 JSON 和空间类型生成直方图;被单列唯一索引覆盖的列也不是直方图的典型使用对象。
  • 统计干扰排查:如果确认直方图导致估算异常,可以先重新生成;仍不合适时再删除,而不是长期保留一份过期统计。
-- 数据分布明显变化后重建统计
ANALYZE TABLE orders
UPDATE HISTOGRAM ON status WITH 32 BUCKETS;

-- 不再需要时删除指定列的直方图
ANALYZE TABLE orders
DROP HISTOGRAM ON status;
MySQL 直方图从 ANALYZE TABLE 维护到 COLUMN_STATISTICS 查看和删除的边界说明图
图2:直方图维护入口、元数据视图、手动或自动更新以及删除边界说明图,属于原创静态结构图,不是截图或运行证据。

一张速查表

问题优先动作不要误解成
非索引列的过滤估算明显失真生成直方图并用 EXPLAIN 对照直方图会替代索引
直方图更新时间很旧按当前分布重建,或配置合适的自动更新统计会随每次写入即时刷新
有直方图但计划没变化检查是否有范围优化或其他成本因素每条查询都会使用直方图
统计让排查更复杂重新生成,必要时 DROP HISTOGRAM保留越多统计越好

MySQL 直方图的价值在于补充列分布信息:它让优化器在没有索引的过滤条件上少一些盲猜。实践时按“生成 → 查看 → EXPLAIN 对照 → 随数据变化维护”的顺序处理,才能把统计信息与执行计划联系起来;如果真正的问题是数据访问路径,仍应回到索引、SQL 形状和连接顺序本身。

相关问题

直方图能不能替代索引?

不能。直方图主要改善估算,索引才负责提供更直接的数据访问路径。是否建索引仍要看查询频率、选择性、写入成本和整体访问模式。

为什么生成直方图后 EXPLAIN 没变化?

可能是优化器已经使用了更优先的范围估算,也可能是当前查询的代价模型不需要这份统计。先看 COLUMN_STATISTICS 是否更新,再结合 EXPLAIN 的访问类型、rows 和 filtered 判断。

数据经常变化时应该选 AUTO UPDATE 吗?

不应只看变化频率。先评估分析成本和估算收益;需要自动维护时可使用 AUTO UPDATE,但仍要关注更新触发条件和统计是否真正适合该列。

直方图看起来不准怎么办?

先检查 last-updated 与 sampling-rate,然后重建直方图并重新查看计划。若列分布或查询模式不适合,删除统计比持续依赖旧数据更清楚。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL ALTER INDEX INVISIBLE 与删除索引的运维区别MySQL ALTER INDEX INVISIBLE 与删除索引的运维区别
上一篇
MySQL ALTER INDEX INVISIBLE 与删除索引的运维区别
MySQL EXPLAIN ANALYZE 中 actual time 两个数怎么读
下一篇
MySQL EXPLAIN ANALYZE 中 actual time 两个数怎么读
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    1018次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1020次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1155次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1121次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    962次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码