mysql explain中的rows和limit有关系吗?

文章讨论了在MySQL中执行SQL查询时,explain命令显示的rows值为何超过预期。作者分析了主键和自增属性对rows估计的影响,以及limit子句在行数计算中的作用,揭示了rows值是根据索引和给定条件估算的,与limit1无关。
摘要由CSDN通过智能技术生成

这周五下班前,发现了一个奇怪问题,大概是这个背景

一张表,结构为

Create Table: CREATE TABLE `out_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=Innodb AUTO_INCREMENT=36865 DEFAULT CHARSET=latin1

总共有37K rows的数据,数据大概是这样

+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | D    |
|  5 | c    |
|  6 | c    |
|  7 | c    |
|  8 | c    |
|  9 | c    |
| 10 | a    |
+----+------+

运行了这个SQL

mysql> select id from out_table where id >10000  limit 1;
+-------+
| id    |
+-------+
| 10001 |
+-------+
1 row in set (0.00 sec)

速度也很快。

可是在运行explain的时候

mysql> explain select id from out_table where id >10000  limit 1;
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+--------------------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows  | Extra                    |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | out_table | range | PRIMARY       | PRIMARY | 4       | NULL | 26358 | Using where; Using index |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+--------------------------+

发现rows居然有,26358

查看MySQL官方文档,rows所代表的含义

ColumnMeaning
rowsEstimate of rows to be examined

翻译过来就是,估计需要检测的行数。

可是从DBA的直觉来说,id字段为主键,且为自增属性,另外后面有个limit 1,那么无论如何rows应该不大于1才对。

那么是否explain没有考虑后面的limit 1呢?

继续运行SQL验证

mysql> explain select id from out_table where id >10000 ;
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+--------------------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows  | Extra                    |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | out_table | range | PRIMARY       | PRIMARY | 4       | NULL | 26358 | Using where; Using index |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+--------------------------+

果然后面的limit 1根本不影响rows的值

那么这个rows是怎么算出来的呢?我们翻看下MySQL源码(以5.6.23为例)。

为了避免不擅长的大段落描述,我把几个关键的文件和函数粘贴出来。

文件关键部分下一步
sql/opt_explain_traditional.cc"push(&items, column_buffer.col_rows, nil)col_rows
sql/opt_explain.ccselect->quick->recordsrecords
sql/opt_range.cccheck_quick_select

而check_quick_select的功能,在MySQL源码中的注释为

Calculate estimate of number records that will be retrieved by a range scan on given index using given SEL_ARG intervals tree.

翻译过来就是,这个方法仅仅根据给出的关于这个索引的条件和索引本身,来判断需要扫描多少行。显然limit 1和这个索引是没有直接关系的。

所以新姿势,get!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MySQL大神

用金钱解决你的烦恼

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值