zoukankan      html  css  js  c++  java
  • 为什么rows这么大,在mysql explain中---写在去acumg听讲座的前一夜

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

    一张表,结构为

    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所代表的含义

    Column Meaning
    rows Estimate 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.cc select->quick->records records
    sql/opt_range.cc check_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!

     

    MySQL限时解答,24小时内友哥专业解答
    http://www.yougemysqldba.com
    如有进一步需要请联系微信onesoft007
    微博账号@友哥一指
  • 相关阅读:
    php学习笔记
    附加题-重构的读后总结
    附加题-stack的理解
    (转)php的扩展和嵌入--php的生命周期与变量详述
    homework-09
    html学习笔记之position
    homework-06
    homework-08
    在windows下使用git需要反复输入用户名和密码的问题
    windows命令行编码与nodejs编码格式冲突的解决方式
  • 原文地址:https://www.cnblogs.com/youge-OneSQL/p/8542486.html
Copyright © 2011-2022 走看看