MySQL状态变量Handler_read_rnd_next增长很多


11

在MYSQL状态下,Handler_read_rnd_next值非常高。

我知道,当执行没有适当索引的查询时,此值将增加。

但是,即使执行“ Handler_read_rnd_next”之类的显示状态,该值也会增加2。

基于此状态标志,我们正在监视一些统计信息。

因此,每次这些统计数据都显示为关键。

我们可以从“ Handler_read_rnd_next”计数中排除这些“显示”执行计数吗?

另一个例子

有一个包含10行的表,该表在“数据”列上建立索引,并且如果我们执行以下查询:

select data from test where data = 'vwx' -> returns one row

如果我们检查'Handler_read_rnd_next'的值,它会增加7。

以下是上述查询的explain命令的结果:

explain select data from test where data = 'vwx';

id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra

1, 'SIMPLE', 'test', 'ref', 'data', 'data', '35', 'const', 1, 'Using where; Using index'

有什么办法可以限制这个值,或者我可以知道为什么这个值越来越快地增加。


这实际上引起性能问题吗?
亚伦·布朗

没有任何性能受到影响,但是监视工具正在检查该标志并显示为严重。
Phanindra

如果性能不是问题,请改正监视工具。
亚伦·布朗

我也检查了其他工具(Monyog),也有同样的问题。
Phanindra '04年

所以呢?如果没有引起性能问题,请忽略它。这只是一个柜台。
亚伦·布朗

Answers:


5

首先,让我们看一下Handler_read_rnd_next的定义。

根据Handler_read_rnd_next上的MySQL文档

读取数据文件下一行的请求数。如果要进行大量表扫描,则此值较高。通常,这表明您的表未正确建立索引,或者未编写查询以利用您拥有的索引。

现在,查看您的查询:

select data from test where data = 'vwx';

您说该表有10行。根据经验,如果需要检查的行数大于总行数的5%,则MySQL Query Optimizer会拒绝使用索引。

让我们做数学。10行的5%为0.5行。即使需要定位数据的行数为1,也大于0.5。基于较低的行数和我刚才提到的索引规则,MySQL Query Optimizer将始终执行表扫描。

由于该列data本身是索引的,而不是表扫描的索引,因此mysql进行了索引扫描。

如果您确定测试表永远不会增长,则可以删除所有索引并进行表扫描。处理程序状态变量应停止递增。


你好,谢谢你的回复。我曾尝试通过删除索引并通过执行查询来检查值。但是Handler_read_rnd_next的值将增加18,而索引的值将增加7。我提到的表格不是固定的。举个例子,我在表中插入了70多行,因此总行数为80,并使用“ data”列上的索引执行了相同的查询,该查询仍然只返回一行。但是,当我检查'Handler_read_rnd_next'的值时,它仍在递增7。我可以知道此标志如何递增的原因以及如何对其进行限制。
Phanindra

我给出的完全相同的原因仍然适用。进行索引扫描。这次,不需要完整的索引。显然,必须遍历索引BTREE中的7个叶节点才能获得一行。处理程序状态计数器显示索引使用情况。如我所说,限制的唯一方法是完全删除索引。否则,这始终是预期的行为。更好地索引更复杂的表结构和正确设计的查询可以减轻处理程序计数,但永远不能完全删除它们。
RolandoMySQLDBA'5

“根据经验,如果需要检查的行数大于总行数的5%,则MySQL Query Optimizer会拒绝使用索引。” -这对了解非常有帮助。是否有任何官方文件支持这一点?非常感谢!
itoctopus19年

2

什么版本的MySQL?

最好在此处记录为什么增加此标志的原因:http : //www.mysqlperformanceblog.com/2010/06/15/what-does-handler_read_rnd-mean/

简而言之,它只是完整或部分表扫描期间按顺序获取的行数的计数器。

那就是说,我得到了不同的结果:

mysql> CREATE TABLE `test` (
    ->   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    ->   `data` varchar(255) NOT NULL,
    ->   PRIMARY KEY (`id`),
    ->   KEY `data` (`data`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.27 sec)

mysql> INSERT INTO test (data) VALUES ('a'), ('b'), ('c'), ('d'), ('e'), ('f'), ('g'), ('h'), ('i'), ('vwx');
Query OK, 10 rows affected (0.06 sec)
Records: 10  Duplicates: 0  Warnings: 0

mysql> FLUSH STATUS;
Query OK, 0 rows affected (0.07 sec)

mysql> select data from test where data = 'vwx';
+------+
| data |
+------+
| vwx  |
+------+
1 row in set (0.04 sec)

mysql> SHOW SESSION STATUS LIKE 'Handler%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Handler_commit             | 1     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 0     |
| Handler_read_key           | 3     |
| Handler_read_last          | 0     |
| Handler_read_next          | 1     |
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 0     |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 0     |
+----------------------------+-------+
16 rows in set (0.15 sec)

0

如果“数据”列上存在唯一/主索引,则说明您已经对该查询进行了优化。我认为无法对此进行进一步的优化。

您还可以验证是否已完成“全表扫描”吗?

SHOW STATUS like 'select_scan'; 
SELECT data from test where data='vmx';
SHOW STATUS like 'select_scan'; 

确保select_scan的值没有增加,这样您可以检查FULL TABLE SCAN是否已完成。您应该尝试优化不会执行FULL TABLE SCAN的查询。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.