如何计算MySQL中的index hit rate(索引命中率)
MySQL索引命中率计算实现方案
- 首先排除二进制日志(binary log)方案:二进制日志仅记录数据变更类操作(增删改),不会存储普通SELECT查询的执行记录,完全无法支撑SELECT索引命中率的统计需求。
粗粒度:实例/会话级整体命中率计算
网上检索到的不支持MySQL的计算方法大多是适配其他数据库的逻辑,MySQL原生自带Handler层计数器,可以直接计算整体命中率,不需要额外采集日志:
执行以下SQL查询累计状态值:
SHOW GLOBAL STATUS WHERE Variable_name IN ('Handler_read_key','Handler_read_rnd_next');
指标含义:
Handler_read_key:通过索引读取行的总次数,数值越高代表索引命中情况越好Handler_read_rnd_next:全表扫描逐行读取的总次数,数值越高代表走全表扫描的查询越多- 命中率计算公式:
索引命中率 = Handler_read_key / (Handler_read_key + Handler_read_rnd_next) * 100%
提示:如果需要统计特定时间段的命中率,在统计开始、结束节点分别查询上述两个值,用差值代入公式计算即可;如果需要统计当前会话的命中率,把SQL里的
GLOBAL替换为SESSION。
细粒度:区分来源、精确到单条查询的命中率统计
如果需要像你给出的示例一样,区分来自不同服务器的查询、统计每条SELECT是否命中自建索引,用慢查询日志+执行计划校验的方案即可:
- 修改MySQL配置,记录所有查询的执行情况:
# my.cnf配置项 slow_query_log = ON long_query_time = 0 log_queries_not_using_indexes = ON
配置生效后,所有执行的SQL、以及未走索引的SQL都会被记录到慢查询日志中。
2. 给不同来源服务器的查询加上来源标记注释,比如服务器1发起的查询写成/* source: server1 */ SELECT * FROM USER WHERE ID = 1,服务器2的查询对应加/* source: server2 */注释,后续统计时按注释分组即可。
3. 解析慢查询日志时,对每条SELECT语句提取执行计划信息,判断是否命中了你创建的目标索引,最终按来源分别统计命中数/总查询数,即可得到对应维度的索引命中率。
你给出的待统计查询样例如下:
SELECT * FROM USER WHERE ID = 1 (Comes From server 1) SELECT * FROM USER WHERE ID = 2 (Comes From server 2) SELECT * FROM USER WHERE ID = 3 (Comes From server 1)
如果USER表的ID字段已创建索引,这3条查询都会走索引检索,对应统计周期内的索引命中率为100%。
内容的提问来源于stack exchange,提问作者roach
相关产品推荐
相关产品推荐

