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

时间: 2024-10-14 00:47:02

MySQL执行SHOW STATUS查询服务器状态状态之Handler_read_* 详解的相关文章

设计模式 - 状态模式(state pattern) 详解

状态模式(state pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 状态模式(state pattern): 允许对象在内部状态改变时改变它的行为, 对象看起来好像修改了它的类. 建立Context类, 包含多个具体状态(concrete state)类的组合, 根据状态的不同调用具体的方法, state.handle(), 包含set\get方法改变状态. 状态接口(state interface), 包含抽象方法handle(),

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

传送带:Linux - CentOS6.5服务器搭建与初始化配置详解(上) 继续接着上面的安装,安装完后会出现下面界面 点击reboot重启 重启后可以看到下面的tty终端界面  因为这就是最小化安装 输入root和之前配置的密码 第一步先把防火墙给光了 iptables -F  命令用于清空规则 这里插一条命令(这个命令我忘记打上去了) /etc/init.d/iptables save  用于保存当前被清空的规则 chkconfig  iptables  stop  开机不允许启动防火墙 c

MySQL Server 5.0–安装及配置/MySQLInstanceConfig.exe用法详解

MySQL Server 5.0–安装及配置/MySQLInstanceConfig.exe用法详解 http://blog.csdn.net/feihong247/article/details/7791105 配置MySQL步骤: 1.       运行MySQL Server安装目录下bin/MySQLInstanceConfig.exe.出现如下所示的向导界面 . 点击"Next"进入下一步. 2.       如果MySQLInstanceConfig在MySQL Serve

NFS服务器原理和安装配置详解附案例演练

NFS服务器原理和安装配置详解附案例演练 1.什么是NFS服务器 NFS就是Network File System的缩写,它最大的功能就是可以通过网络,让不同的机器.不同的操作系统可以共享彼此的文件. NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文件系统中,而在本地端的系统中来看,那个远程主机的目录就好像是自己的一个磁盘分区一样,在使用上相当便利: 2.NFS挂载原理 NFS服务器的挂载结构图: 如上图示: 当我们在NFS服务器设置好一个共享目录/home/public后

DNS服务器的搭建与使用详解

DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串.通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析).DNS协议运行在UDP协议之上,使用端口号为53. 1.网络环境图示 2.分别在两台服务器ns1和ns2上通过YUM安装Bind软件包 [[email protected] ~]# yum install bind [[email pro

MySQL影响性能的因素原因以及性能优化配置详解

(https://blog.csdn.net/kangshuo2471781030/article/details/79315577) 一.MySQL性能优化之-影响性能的因素 1.商业需求的影响 不合理需求造成资源投入产出比过低,这里我们就用一个看上去很简单的功能来分析一下. 需求:一个论坛帖子总量的统计,附加要求:实时更新 从功能上来看非常容易实现,执行一条SELECT COUNT(*) from 表名的Query 就可以得到结果.但是,如果我们采用不是MyISAM 存储引擎,而是使用的In

Nginx服务器搭建和基本配置详解

nginx Nginx(engine X) 是一个高性能的 HTTP 服务器和反向代理服务器,这款软件开发的目的是为了解决 C10k 问题. Nginx 的架构利用了许多现代操作系统的特性,以实现一个高性能的 HTTP 服务器.例如在 Linux 系统上,Nginx 使用了 epoll,sendfile,File AIO,DIRECTIO 等机制,使得 Nginx 不仅性能高效,而且资源占用率非常低,官方宣称 nginx 维持 10000 个非活动的 HTTP keep-alive 连接仅需要

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

一.NFS服务简介        NFS是Network  File System(网络文件系统).主要功能是通过网络让不同的服务器之间可以共享文件或者目录.NFS客户端一般是应用服务器(比如web,负载均衡等),可以通过挂载的方式将NFS服务器端共享的目录挂载到NFS客户端本地的目录下.       NFS在文件传送过程中依赖与RPC(远程过程调用)协议.NFS本身是没有提供信息传送的协议和功能的,但是能够用过网络进行图片,视频,附件等分享功能.只要用到NFS的地方都需要启动RPC服务,不论是

【转】Mysql之inner join,left join,right join详解

首先借用官方的解释下: inner join(等值连接):只返回两个表中联结字段相等的行: left join(左联接):返回包括左表中的所有记录和右表中联结字段相等的记录: right join(右联接):返回包括右表中的所有记录和左表中联结字段相等的记录. 比如我们有xs.cj两个表 xs表 cj表 --------------- ---------------------- id name id score 1 张三 1 96 2 李四 2 80 3 86 Sql代码 1 SELECT *