MySQL执行SHOW STATUS查询服务器状态状态之Handler_read_* 详解
在MySQL里,我们一般使用SHOW STATUS查询服务器状态,语法一般来说如下:
SHOW [GLOBAL | SESSION] STATUS [LIKE ‘pattern’ | WHERE expr]
执行命令后会看到很多内容,其中有一部分是Handler_read_*,它们显示了数据库处理SELECT查询语句的状态,对于调试SQL语句有很大意义,可惜实际很多人并不理解它们的实际意义,本文简单介绍一下:
为了让介绍更易懂,先建立一个测试用的表:
CREATE TABLE `foo` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`col1` varchar(10) NOT NULL,
`col2` text NOT NULL,
PRIMARY KEY (`id`),
KEY `col1` (`col1`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=gbk
mysql> INSERT INTO `foo` (`id`, `col1`, `col2`) VALUES (1, "a", "a"), (2, "b", "b"), (3, "c", "c"), (4, "d", "d"), (5, "e", "e"), (6, "f", "f"), (7, "g", "g"), (8, "h", "h"), (9, "i", "i");
在下面的测试里,每次执行SQL时按照如下过程执行:
FLUSH STATUS;
SELECT …;
SHOW SESSION STATUS LIKE ‘Handler_read%’;
EXPLAIN SELECT …;
Handler_read_first
The number of times the first entry was read from an index. If this value is high, it suggests that the server is doing a lot of full index scans; for example, SELECT col1 FROM foo, assuming that col1 is indexed.
此选项表明SQL是在做一个全索引扫描,注意是全部,而不是部分,所以说如果存在WHERE语句,这个选项是不会变的。如果这个选项的数值很大,既是好事 也是坏事。说它好是因为毕竟查询是在索引里完成的,而不是数据文件里,说它坏是因为大数据量时,简便是索引文件,做一次完整的扫描也是很费时的。
FLUSH STATUS; SELECT col1 FROM foo;
mysql> SHOW SESSION STATUS LIKE "%handler_read%";
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 1 |
| Handler_read_key | 1 |
| Handler_read_last | 0 |
| Handler_read_next | 9 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 0 |
+-----------------------+-------+
7 rows in set (0.03 sec)
mysql> EXPLAIN SELECT col1 FROM foo\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: foo
type: index
possible_keys: NULL
key: col1
key_len: 22
ref: NULL
rows: 9
Extra: Using index
1 row in set (0.01 sec)
Handler_read_key
The number of requests to read a row based on a key. If this value is high, it is a good indication that your tables are properly indexed for your queries.
此选项数值如果很高,那么恭喜你,你的系统高效的使用了索引,一切运转良好。
FLUSH STATUS; mysql> SELECT * FROM foo WHERE col1="e";
+----+------+------+
| id | col1 | col2 |
+----+------+------+
| 5 | e | e |
+----+------+------+
1 row in set (0.02 sec)
mysql> SHOW SESSION STATUS LIKE "%handler_read%";
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 0 |
| Handler_read_key | 1 |
| Handler_read_last | 0 |
| Handler_read_next | 1 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 0 |
+-----------------------+-------+
7 rows in set (0.02 sec)
mysql> explain SELECT * FROM foo WHERE col1="e";
+----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
| 1 | SIMPLE | foo | ref | col1 | col1 | 22 | const | 1 | Using index condition |
+----+-------------+-------+------+---------------+------+---------+-------+------+-----------------------+
1 row in set (0.01 sec)
Handler_read_next
The number of requests to read the next row in key order. This value is incremented if you are querying an index column with a range constraint or if you are doing an index scan.
此选项表明在进行索引扫描时,按照索引从数据文件里取数据的次数。
mysql> FLUSH STATUS;
Query OK, 0 rows affected (0.00 sec) mysql> SELECT col1 FROM foo ORDER BY col1 ASC;
+------+
| col1 |
+------+
| a |
| b |
| c |
| d |
| e |
| f |
| g |
| h |
| i |
+------+
9 rows in set (0.01 sec)
mysql> SHOW SESSION STATUS LIKE "%handler_read%";
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 1 |
| Handler_read_key | 1 |
| Handler_read_last | 0 |
| Handler_read_next | 9 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 0 |
+-----------------------+-------+
7 rows in set (0.01 sec)
mysql> explain SELECT col1 FROM foo ORDER BY col1 ASC\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: foo
type: index
possible_keys: NULL
key: col1
key_len: 22
ref: NULL
rows: 9
Extra: Using index
1 row in set (0.00 sec) ERROR:
No query specified
Handler_read_prev
The number of requests to read the previous row in key order. This read method is mainly used to optimize ORDER BY … DESC.
此选项表明在进行索引扫描时,按照索引倒序从数据文件里取数据的次数,一般就是ORDER BY … DESC。
mysql> FLUSH STATUS;
Query OK, 0 rows affected (0.00 sec) mysql> SELECT col1 FROM foo ORDER BY col1 DESC;
+------+
| col1 |
+------+
| i |
| h |
| g |
| f |
| e |
| d |
| c |
| b |
| a |
+------+
9 rows in set (0.01 sec)
mysql> SHOW SESSION STATUS LIKE "%handler_read%";
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 0 |
| Handler_read_key | 1 |
| Handler_read_last | 1 |
| Handler_read_next | 0 |
| Handler_read_prev | 9 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 0 |
+-----------------------+-------+
7 rows in set (0.03 sec)
mysql> explain SELECT col1 FROM foo ORDER BY col1 DESC;
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | foo | index | NULL | col1 | 22 | NULL | 9 | Using index |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.01 sec)
Handler_read_rnd
The number of requests to read a row based on a fixed position. This value is high if you are doing a lot of queries that require sorting of the result. You probably have a lot of queries that require MySQL to scan entire tables or you have joins that don’t use keys properly.
简单的说,就是查询直接操作了数据文件,很多时候表现为没有使用索引或者文件排序。
mysql> FLUSH STATUS;
Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM foo ORDER BY col2 DESC;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
| 9 | i | i |
| 8 | h | h |
| 7 | g | g |
| 6 | f | f |
| 5 | e | e |
| 4 | d | d |
| 3 | c | c |
| 2 | b | b |
| 1 | a | a |
+----+------+------+
9 rows in set (0.02 sec)
mysql> SHOW SESSION STATUS LIKE "%handler_read%";
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 1 |
| Handler_read_key | 10 |
| Handler_read_last | 0 |
| Handler_read_next | 0 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 9 |
| Handler_read_rnd_next | 10 |
+-----------------------+-------+
7 rows in set (0.02 sec)
mysql> explain SELECT * FROM foo ORDER BY col2 DESC;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | foo | ALL | NULL | NULL | NULL | NULL | 9 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.01 sec)
Handler_read_rnd_next
The number of requests to read the next row in the data file. This value is high if you are doing a lot of table scans. Generally this suggests that your tables are not properly indexed or that your queries are not written to take advantage of the indexes you have.
此选项表明在进行数据文件扫描时,从数据文件里取数据的次数。
mysql> FLUSH STATUS;
Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM foo;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
| 1 | a | a |
| 2 | b | b |
| 3 | c | c |
| 4 | d | d |
| 5 | e | e |
| 6 | f | f |
| 7 | g | g |
| 8 | h | h |
| 9 | i | i |
+----+------+------+
9 rows in set (0.01 sec)
mysql> SHOW SESSION STATUS LIKE "%handler_read%";
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 1 |
| Handler_read_key | 1 |
| Handler_read_last | 0 |
| Handler_read_next | 0 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 10 |
+-----------------------+-------+
7 rows in set (0.02 sec)
mysql> EXPLAIN SELECT * FROM foo\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: foo
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 9
Extra: NULL
1 row in set (0.01 sec)
后记:不同平台,不同版本的MySQL,在运行上面例子的时候,Handler_read_*的数值可能会有所不同,这并不要紧,关键是你要意识到 Handler_read_*可以协助你理解MySQL处理查询的过程,很多时候,为了完成一个查询任务,我们往往可以写出几种查询语句,这时,你不妨挨 个按照上面的方式执行,根据结果中的Handler_read_*数值,你就能相对容易的判断各种查询方式的优劣。
说到判断查询方式优劣这个问题,就再顺便提提show profile语法,在新版MySQL里提供了这个功能:
mysql> set profiling=on;
Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> show profile;
+----------------+----------+
| Status | Duration |
+----------------+----------+
| starting | 0.000840 |
| query end | 0.000116 |
| closing tables | 0.000097 |
| freeing items | 0.000102 |
| cleaning up | 0.000205 |
+----------------+----------+
5 rows in set, 1 warning (0.01 sec) mysql> show profiles;
+----------+------------+-------------------+
| Query_ID | Duration | Query |
+----------+------------+-------------------+
| 1 | 0.00135925 | show warnings |
| 2 | 0.00127000 | show warnings |
| 3 | 0.18649600 | SELECT * FROM foo |
+----------+------------+-------------------+
3 rows in set, 1 warning (0.00 sec)
http://www.path8.net/tn/archives/5613
参考链接:http://www.shinguz.ch/MySQL/mysql_handler_read_status.html
from http://hi.baidu.com/thinkinginlamp/blog/item/31690cd7c4bc5cdaa144df9c.html
MySQL执行SHOW STATUS查询服务器状态状态之Handler_read_* 详解的更多相关文章
- HTTP 状态响应码 意思详解/大全
HTTP 状态响应码 意思详解/大全 转:http://blog.csdn.net/helin916012530/article/details/29842595 HTTP状态码(HTTP Statu ...
- Linux - CentOS6.5服务器搭建与初始化配置详解(下)
传送带:Linux - CentOS6.5服务器搭建与初始化配置详解(上) 继续接着上面的安装,安装完后会出现下面界面 点击reboot重启 重启后可以看到下面的tty终端界面 因为这就是最小化安装 ...
- MySQL单列索引和组合索引(联合索引)的区别详解
发现index merge局限性,优化器会自动判断是否使用 index merge 优化技术,查询还是需要组合索引[推荐阅读:对mysql使用索引的误解] MySQL单列索引和组合索引(联合索引)的区 ...
- mysql用户授权、数据库权限管理、sql语法详解
mysql用户授权.数据库权限管理.sql语法详解 —— NiceCui 某个数据库所有的权限 ALL 后面+ PRIVILEGES SQL 某个数据库 特定的权限SQL mysql 授权语法 SQL ...
- Linux NFS服务器的安装与配置详解
一.NFS服务简介 NFS是Network File System(网络文件系统).主要功能是通过网络让不同的服务器之间可以共享文件或者目录.NFS客户端一般是应用服务器(比如web,负载均衡等),可 ...
- linux高性能服务器编程 (三) --TCP协议详解
第三章 IP协议详解 TCP协议是TCP/IP协议族中的另外一个重要的协议,与IP协议相比,TCP协议更高进应用层.一些重要的socket选项都和TCP协议相关.这一章主要从如下方面学习: 1)TCP ...
- mysql事务、redo日志、undo日志、checkpoint详解
转载: https://zhuanlan.zhihu.com/p/34650908 事务: 说起mysql innodb存储引擎的事务,首先想到就是ACID(不知道的请google),数据库是如何做到 ...
- mysql中文、英文别名排序问题,order by 关键字详解
order by 关键字详解: SELECT intcode AS 商品编码, product_title AS 名称, retailprice AS 零售价, purchaseprice AS ...
- CentOS 6.3下Samba服务器的安装与配置详解
一.简介 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写,即为服务器消息块 ,SMB主要是作为Microsoft的 ...
随机推荐
- 性能测试-Jmeter
缘由 很多情况下我们写程序过程中只会对固定模块采取并发限制,而且asp.net对于多线程也有他自己的处理机制,尤其对于注重业务,结果导向的团队可能更注重一定时间节点给出满意的产品,但是你的模块到底是否 ...
- 在JSP中使用CKEditor网页编辑器
为了在我的一个项目使用CKEditor网页编辑器,我开始了寻找应用之法. 我下载了ckeditor_4.3.3_standard和ckeditor-java-core-3.5.3. 之前的版本和现在版 ...
- iOS9对SDK的影响(iOS9适配必看)
1.大部分社交平台接口不支持https协议. 问题描述:在iOS9下,系统默认会拦截对http协议接口的访问,因此无法获取http协议接口的数据.对ShareSDK来说,具体表现可能是,无法授权. ...
- 2 weekend110的HDFS的JAVA客户端编写 + filesystem设计思想总结
HDFS的JAVA客户端编写 现在,我们来玩玩,在linux系统里,玩eclipse 或者, 即,更改图标,成功 这个,别慌.重新换个版本就好,有错误出错是好事. http://www.eclips ...
- XSS攻击及防御(转)
add by zhj: 略有修改.另外还有一篇文章值得参考,使用 PHP 构建的 Web 应用如何避免 XSS 攻击,总得来说防御XSS的方法是客户端和服务端都 要对输入做检查,如果只有客户端做检查, ...
- RFID第二次作业
1.简述智能卡的发展,以及射频电子标签在其中所处的位置. 智能卡(Smart Card)又称为集成电路卡(IC卡),内部带有微处理器和存储单元等部件. 射频电子标签是一种非接触式的IC卡,是后期发展起 ...
- tty & pty & pts
[tty & pty & pts] 基本概念: 1> tty(终端设备的统称):tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过 ...
- Field 'SCHED_TIME' doesn't have a default value
出现这个情况的原因是: 我jar包使用的是quartz-2.1.7版本,但是初始化集群的dbTables脚本用的却是2.2.1版本的,导致出现这个异常,改用2.1.7的dbTables脚本之后即解决问 ...
- socket的一个错误的解释SocketException以及其他几个常见异常
写socket程序有可能会遇见这个问题 其他信息: 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受. 这种情况我的 错误原因 ...
- jshint 安装使用
首先要安装nodjs, 参考另一篇文章: Ubuntu 编译安装node.js 然后运行 npm install jshint -g 之后在要扫描的目录下运行命令 jshint . >> ...