在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_* 详解的更多相关文章

  1. HTTP 状态响应码 意思详解/大全

    HTTP 状态响应码 意思详解/大全 转:http://blog.csdn.net/helin916012530/article/details/29842595 HTTP状态码(HTTP Statu ...

  2. Linux - CentOS6.5服务器搭建与初始化配置详解(下)

    传送带:Linux - CentOS6.5服务器搭建与初始化配置详解(上) 继续接着上面的安装,安装完后会出现下面界面 点击reboot重启 重启后可以看到下面的tty终端界面  因为这就是最小化安装 ...

  3. MySQL单列索引和组合索引(联合索引)的区别详解

    发现index merge局限性,优化器会自动判断是否使用 index merge 优化技术,查询还是需要组合索引[推荐阅读:对mysql使用索引的误解] MySQL单列索引和组合索引(联合索引)的区 ...

  4. mysql用户授权、数据库权限管理、sql语法详解

    mysql用户授权.数据库权限管理.sql语法详解 —— NiceCui 某个数据库所有的权限 ALL 后面+ PRIVILEGES SQL 某个数据库 特定的权限SQL mysql 授权语法 SQL ...

  5. Linux NFS服务器的安装与配置详解

    一.NFS服务简介 NFS是Network File System(网络文件系统).主要功能是通过网络让不同的服务器之间可以共享文件或者目录.NFS客户端一般是应用服务器(比如web,负载均衡等),可 ...

  6. linux高性能服务器编程 (三) --TCP协议详解

    第三章 IP协议详解 TCP协议是TCP/IP协议族中的另外一个重要的协议,与IP协议相比,TCP协议更高进应用层.一些重要的socket选项都和TCP协议相关.这一章主要从如下方面学习: 1)TCP ...

  7. mysql事务、redo日志、undo日志、checkpoint详解

    转载: https://zhuanlan.zhihu.com/p/34650908 事务: 说起mysql innodb存储引擎的事务,首先想到就是ACID(不知道的请google),数据库是如何做到 ...

  8. mysql中文、英文别名排序问题,order by 关键字详解

    order by 关键字详解:   SELECT intcode AS 商品编码, product_title AS 名称, retailprice AS 零售价, purchaseprice AS ...

  9. CentOS 6.3下Samba服务器的安装与配置详解

    一.简介 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写,即为服务器消息块 ,SMB主要是作为Microsoft的 ...

随机推荐

  1. RPC进阶篇

    RPC实现结构拆解 RPC过程调用详解:RPC 服务端通过 RpcServer 去导出(export)远程接口方法,而客户端通过 RpcClient 去引入(import)远程接口方法. 客户端像调用 ...

  2. 60个响应式的Web设计教程–能够手机访问!

    想要学习响应式[responsive:屏幕自适应的效果]的网页设计和开发技术?在这个超大的收藏集合中,我想你定会找到想要开始学习的响应式网页设计教程. 面对超过1亿的手机互联网用户,开发专业和用户友好 ...

  3. 数据结构 -- 图的最短路径 Java版

    作者版权所有,转载请注明出处,多谢.http://www.cnblogs.com/Henvealf/p/5574455.html 上一篇介绍了有关图的表示和遍历实现.数据结构 -- 简单图的实现与遍历 ...

  4. axis1调用方式

    axis http://10.15.22.28/itfmgr/services/ITaxManagement?wsdl package com.isoftstone.core.service.impl ...

  5. Keil MDK Code、RO-data、RW-data、ZI-data数据段

      Program Size: Code=10848 RO-data=780 RW-data=372 ZI-data=868   Code 表示程序代码指令部分 存放在Flash区 RO-data 表 ...

  6. 通过set和waitOne来控制子线程的运行和停止

    public partial class Form1 : Form { //自动重置事件类 //主要用到其两个方法 WaitOne() 和 Set() , 前者阻塞当前线程,后者通知阻塞线程继续往下执 ...

  7. So many good projects for studying C programming lanuage.

    Some one asked a question for studying C programming language on stackexachange.com. He got a bucket ...

  8. StringUtils 字符串工具类

    package com.thinkgem.jeesite.common.utils; import java.io.File; import java.io.IOException; import j ...

  9. WinForm设置窗体默认控件焦点

    winform窗口打开后文本框的默认焦点设置,进入窗口后默认聚焦到某个文本框,两种方法: ①设置tabindex 把该文本框属性里的tabIndex设为0,焦点就默认在这个文本框里了. ②Winfor ...

  10. STM32 使用 printf 发送数据配置方法 -- 串口 UART, JTAG SWO, JLINK RTT

    STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK) http://home.eeworld.com.cn/my/space-uid-338727-blogid-47 ...