在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. CentOS下安装R

    R的Windows版本有直接的安装包,直接下载安装很方便,但是对于CentOS6以上,不能直接通过yum 安装R,需要自己编译. 1. 在编译之前,用yum安装各种软件 (1)安装gcc > y ...

  2. TopFreeTheme精选免费模板【20130701.特别版】

    今天我们整理了16款WordPress和Joomla的最新主题.它们都是来自Themeforest,RocketTheme,YooTheme以及TemPlaza的高质量主题,赶快收藏起来吧. Este ...

  3. 最好的10本适用于初学者阅读的javaScript和jQuery书籍

    现在有许多方式学习新的内容,但是对于刚开始学习和寻找真正沉迷其中的平和状态的人而言,经典的纸质书籍依旧是首选.我发现阅读一本纸质书籍会让自己远离那些在使用电脑和平板时出现的令人不安的情绪.电子书和播客 ...

  4. 关于面试mysql优化的几点纪要

    1.减少查询次数 ,如何减少 ?  2. 表结构优化,如何优化 ? 3. 列选取原则  ? 4.建索引原则   ? 5.mysql语句优化 ?   6.增加mysql处理性能 ? 通过这几点, 再来说 ...

  5. 僵尸进程&孤儿进程

    http://www.cnblogs.com/Anker/p/3271773.html

  6. Hadoop2.2.0 自动切换HA环境搭建

    自动切换的HA,比手动切换HA集群多了一个zookeeper集群 机器分配: zookeeper:hadoop4,hadoop5,hadoop6 namenode:hadoop4,hadoop5 da ...

  7. Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱(转)

    原文:http://www.52nlp.cn/python-网页爬虫-文本处理-科学计算-机器学习-数据挖掘 曾经因为NLTK的缘故开始学习Python,之后渐渐成为我工作中的第一辅助脚本语言,虽然开 ...

  8. 【MySql】在Linux下安装MySql数据库

    [参数环境] 1.Host OS:Win7 64bit 2.VM: VMware 11.1.0 3.Client OS:CentOS 6 4.系统中已安装的openssl版本: openssl-1.0 ...

  9. tty & pty & pts

    [tty & pty & pts] 基本概念: 1> tty(终端设备的统称):tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过 ...

  10. Objective C静态代码扫描和代码质量管理 OClint + SonarQube

    OClint是针对C, C++及Objective C代码的静态扫描分析工具,而SonarQube是一个开源的代码质量管理平台.本文将实现将OClint的扫描结果导入到SonarQube中,已实现对O ...