MySQL执行SHOW STATUS查询服务器状态状态之Handler_read_* 详解

news/2024/7/7 14:32:48

 在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


http://www.niftyadmin.cn/n/3566368.html

相关文章

VMware下OSSIM 5.2.0的下载、安装和初步使用(图文详解)

不多说,直接上干货! 入门阶段不建议选用最新的版本。  采用OSSIM 4.11 到 OSSIM5.0.3 之间任何版本做实验,sensor的状态都会是“V”。 建议,入门,采用OSSIM5.0.0 下载: 链接:https://pan.baidu.com/s/1…

CppUnit - 测试驱动开发入门

测试驱动开发是一个现在软件界最流行的词汇之一,可是很多人还是不得其门而入。这篇文章想通过对于 CppUnit的介绍,给予读者一个基本的映像。如果你熟知CppUnit的使用,请参阅我的另一篇文章:CppUnit代码简介 - 第一部分&#xff0c…

音频程序学习

#pragma comment(lib,"winmm") #include <mmsystem.h> #include <mmreg.h> waveOutOpen函数介绍2007-08-30 19:08(from MSDN) 这个函数打开一个给定的波形音频输出装置来进行回放。 &#xff08;The waveOutOpen function opens the given waveform-audi…

xargs参数代换

xargs 的作用是产生命令需要的参数&#xff0c;主要是用于在命令结合管道的使用中给一些不支持管道的命令提供输入参数。例如&#xff1a;利用find找出~ 目录下由特殊权限的文件&#xff0c;并用ls命令列出文件列表&#xff1a;[whxlocalhost ~]$ find ~ -perm 7000 | ls-l tot…

CppUnit使用指南

测试驱动开发的原则&#xff1a; 先写测试代码&#xff0c;然后编写符合测试的代码。至少做到完成部分代码后&#xff0c;完成对应的测试代码&#xff1b; 测试代码不需要覆盖所有的细节&#xff0c;但应该对所有主要的功能和可能出错的地方有相应的测试用例…

BMP图像文件存储结构(1)

5.1.2 BMP图像文件存储结构&#xff08;1&#xff09; BMP文件存储结构的格式可以在Windows中的WINGDI.h文件中找到定义。 BMP文件总体上由4部分组成&#xff0c;分别是位图文件头、位图信息头、调色板和图像数据&#xff0c;如表5-1所示。 表5-1 BMP文件的组成结构位图文件头…

Jenkins 部署

转自 http://www.cnblogs.com/kevingrace/p/5651427.html Jenkins通过脚本任务触发&#xff0c;实现代码的自动化分发&#xff0c;是CI持续化集成环境中不可缺少的一个环节。下面对Jenkins环境的部署做一记录。--------------------------------------------------------------…

分组查询最大/最小值sql

经典题目&#xff1a;查询每个班级的最高分&#xff0c;查询每种日志的最晚记录 1.查询每个班级的最高分&#xff08;不考虑同一分数的&#xff09; SQL语句&#xff1a; SELECT id,name,calssid,MAX(score) FROM (SELECT * FROM t_zhb ORDER BY score desc) A GROUP BY calssi…