mysql handler read_MySQL handler解读

参数解读

各参数含义参考这个连接(摘抄如下):MySQL Handler

mysql> show global status like 'Handle%';

+----------------------------+---------------+

| Variable_name              | Value        |

+----------------------------+---------------+

| Handler_commit            | 292547310    |

| Handler_delete            | 20004688      |

| Handler_discover          | 0            |

| Handler_external_lock      | 298778503    |

| Handler_mrr_init          | 0            |

| Handler_prepare            | 89764296      |

| Handler_read_first        | 84936796      |

| Handler_read_key          | 197690980    |

| Handler_read_last          | 25            |

| Handler_read_next          | 449603395282  |

| Handler_read_prev          | 488140        |

| Handler_read_rnd          | 17904308      |

| Handler_read_rnd_next      | 2234678057572 |

| Handler_rollback          | 3965287      |

| Handler_savepoint          | 2            |

| Handler_savepoint_rollback | 566          |

| Handler_update            | 150669454    |

| Handler_write              | 1392716731    |

+----------------------------+---------------+

18 rows in set (0.00 sec)

| Handler_commit            | 内部提交语句数

| Handler_delete            | 请求从表中删除行的次数。

| Handler_discover          | MySQL服务器可以问NDB CLUSTER存储引擎是否知道某一名字的表。这被称作发现。Handler_discover说明通过该方法发现的次数。

| Handler_external_lock          |  此变量与锁定操作数量有关,主要是在表访问的开始和结束时起作用。

| Handler_mrr_init            |  服务器使用存储引擎自己实现的多范围读取的次数。

| Handler_prepare            |  用于两阶段提交操作的准备阶段的计数器。

| Handler_read_first        | 索引中第一条被读的次数。如果较高,它建议服务器正执行大量全索引扫描;例如,SELECT col1 FROM foo,假定col1有索引。

| Handler_read_key          | 根据键读一行的请求数。如果较高,说明查询和表的索引正确。

| Handler_read_last            | 根据键读最后一行的请求数。

| Handler_read_next          | 按照键顺序读下一行的请求数。如果你用范围约束或如果执行索引扫描来查询索引列,该值增加。

| Handler_read_prev          | 按照键顺序读前一行的请求数。该读方法主要用于优化ORDER BY … DESC。

| Handler_read_rnd          | 根据固定位置读一行的请求数。如果你正执行大量查询并需要对结果进行排序该值较高。你可能使用了大量需要MySQL扫描整个表的查询或你的连接没有正确使用索引。

| Handler_read_rnd_next      | 在数据文件中读下一行的请求数。如果你正进行大量的表扫描,该值较高。通常说明你的表索引不正确或写入的查询没有利用索引。

| Handler_rollback          | 内部ROLLBACK语句的数量

| Handler_savepoint              | 在一个存储引擎放置一个保存点的请求数量。

| Handler_savepoint_rollback  | 在一个存储引擎的要求回滚到一个保存点数目。

| Handler_update            | 请求更新表中一行的次数。

| Handler_write              | 请求向表中插入一行的次数。

Handler_read_rnd_next的值高则意味着查询运行低效,并且应该建立索引补救或优化。这个值的含义是在数据文件中读取下一行的请求数。如果正在进行大量的表扫描,Handler_read_rnd_next的值比较高通常说明表索引不正确或写入的查询没有有效利用索引。

实际优化中比较看重的几个参数

Handler_read_first和Handler_read_rnd_next

如果前者值较大,说明可能是一个全索引扫描,此外走全表也可能导致这个值比较大;后者值较大,说明扫描的行非常多,可能没有合理的使用索引

Handler_read_key

如果这个值比较大,说明索引使用良好

案例

SELECT CASE WHEN O.FD_ORDER_BUS_TYPE = 1 THEN '自营' ELSE '他营' END AS FD_ORDER_BUS_TYPE, S.SUPPLIER_NAME, G.GOODS_CODE, G.GOODS_NAME, D.FD_NUM

, D.FD_UNIT_NAME, CASE WHEN D.FD_IS_GIFT = '1' THEN '是' ELSE '否' END AS FD_IS_GIFT, (

SELECT dic.dic_name

FROM plat_system_dictionary dic

WHERE dic.DIC_VALUE = D.FD_GIFT_TYPE

AND dic.DIC_DICTYPE_CODE = 'giftType'

) AS FD_GIFT_TYPE_NAME, D.FD_UNIT_PRICE, D.FD_TOTAL_PRICE

, O.FD_ID, O.FD_NO, C.fd_code, C.fd_name, DATE_FORMAT(O.FD_ORDER_DATE, '%Y-%m-%d') AS FD_ORDER_DATE

, (

SELECT CR.fd_code

FROM plat_shop_customer_info CR

WHERE CR.fd_id = O.FD_REC_ORG_ID

) AS FD_REC_ORG_CODE, O.FD_REC_ORG_NAME, (

SELECT CB.fd_code

FROM plat_shop_customer_info CB

WHERE CB.fd_id = O.FD_BILL_ORG_ID

) AS FD_BILL_ORG_CODE, O.FD_BILL_ORG_NAME, CASE WHEN O.FD_IS_TRAN_DIRECT = '1' THEN '是' ELSE '否' END AS FD_IS_TRAN_DIRECT

, CASE WHEN O.FD_IS_ALL_BILL = '1' THEN '是' ELSE '否' END AS FD_IS_ALL_BILL, (

SELECT dic.dic_name

FROM plat_system_dictionary dic

WHERE dic.DIC_VALUE = O.FD_ORDER_STATUS

AND dic.DIC_DICTYPE_CODE = 'orderStatus'

) AS FD_ORDER_STATUS_NAME, O.NC_ORDER_CODE, a.AREATYPE_NAME, U.SYSUSER_NAME AS CREATE_USER_NAME

, substring_index(O.FD_CONTACTS_INFO, ':', 1) AS FD_LINKMAN, substring_index(O.FD_CONTACTS_INFO, ':', -1) AS FD_MOBILE_NUMBER, O.FD_REC_ADDR AS FD_ADDRESS, D.FD_DESC

FROM plat_shop_order_detail D

LEFT JOIN plat_shop_order O ON O.FD_ID = d.FD_ORDER_ID

LEFT JOIN plat_shop_customer_info C ON o.FD_ORDER_ORG_ID = C.fd_id

LEFT JOIN plat_shop_areatype a ON o.FD_AREATYPE_ID = a.AREATYPE_ID

LEFT JOIN plat_shop_goods G ON G.GOODS_ID = D.FD_GOODS_ID

LEFT JOIN plat_shop_supplier S ON G.GOODS_SUPPLIER_ID = S.SUPPLIER_ID

LEFT JOIN plat_system_sysuser U ON U.SYSUSER_ID = O.FD_CREATE_USER_ID

LEFT JOIN plat_system_sysuser U1 ON U1.SYSUSER_ID = O.FD_PLAT_AUDIT_USER_ID

WHERE 1 = 1

AND O.FD_BILL_TYPE = '1'

AND O.FD_BILL_TYPE = '1'

AND O.FD_ORDER_BUS_TYPE = '2'

AND O.FD_ORDER_STATUS = '3'

ORDER BY O.FD_NO DESC;

几张表的数据量都很小,均是不到1W行的水平,然而执行时间接近2s,查看执行计划,可以发现O表和dic表都走的全表,但行数都不算太大,一个4000+,一个1000+

f20fff239ad2

其中O表的using filesort显得比较扎眼,初步判断执行慢是因为排序造成的

对O表添加联合索引,发现需要添加的字段还挺多,而且这些字段的选择性都奇差无比;索引添加完成后,执行时间几乎没有缩短,说明这个filesort并不是查询慢的根本原因。查看handler状态

1.flush status;

2.执行语句

3.show status like '%handler_read%';

可以看到Handler_read_rnd_next高达400W,前面添加的索引几乎没起作用

f20fff239ad2

对gic表添加索引后,Handler_read_rnd_next值下降到6000,执行时间下降为原来的1/10

f20fff239ad2

O表的索引删除后,Handler_read_rnd_next值无变化,执行时间无变化,考虑到O表较小,而且索引列的选择性都奇差无比,这个索引实在是没有存在的必要,故删除该索引

最终的执行计划如下

f20fff239ad2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值