• MySQL explain 中的 rows 究竟是如何计算的?


    今天同事在处理系统慢SQL时遇到几个疑惑的问题,简单描述如下~

    【背景铺垫】

    相关表:

    CREATE TABLE test_table (
      id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
      name varchar(32) NOT NULL,
      PRIMARY KEY (id)
    ) ENGINE = InnoDB CHARSET = utf8mb4;

    test_table 表记录数约12w+

    问题描述

    相关SQL:

    EXPLAIN SELECT COUNT(*)
    
    FROM test_table
    
    WHERE id >= 10534
    
    AND id <= 15375;

    疑问1:上述SQL理应按id主键(聚簇索引)范围查找,为啥explain里的rows会多余两者之差呢?

    在SQL结尾处增加 LIMIT 10 后,rows数值竟然没有任何影响(觉得可能会变为: 10)。

    EXPLAIN SELECT COUNT(*)
    
    FROM test_table
    
    WHERE id >= 10000
    
    LIMIT 10;

    疑问2:LIMIT值不会影响rows的值么?

    rows究竟是怎么计算的呢?

    这个rows在官网文档中的解释如下:

    rows (JSON name: rows)

    The rows column indicates the number of rows MySQL believes it must examine to execute the query.

    For [InnoDB] tables, this number is an estimate, and may not always be exact.

    http://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain_rows

    简单理解即:这个rows就是mysql认为估计需要检测的行数。

    为了探究rows究竟是如何算出来的,查找MYSQL源码来看看:

    文件1:sql/opt_explain_traditional.cc
       关键部分:push(&items, column_buffer.col_rows, nil)
    文件2:sql/opt_explain.cc
       关键部分:select->quick->records
    文件3: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.

    简单翻译就是:这个方法仅仅根据给出的关于这个索引的条件和索引本身,来判断需要扫描多少行。

    总结

    MySQL Explain 里的 rows 这个值

    • 是MySQL认为它要检查的行数(仅做参考),而不是结果集里的行数;
    • 同时 SQL里的 LIMIT 和这个也是没有直接关系的。

    另外,很多优化手段,例如关联缓冲区和查询缓存,都无法影响到rows的显示。MySQL可能不必真的读所有它估计到的行,它也不知道任何关于操作系统或硬件缓存的信息。

  • 相关阅读:
    Mysql:Group Replication & Replication
    使用winsw包装服务将nginx包装为Windows服务
    Nginx的一些常用配置
    在ASP.NET Core 2.0中使用Facebook进行身份验证
    展现层实现增删改查
    ABP创建应用服务
    ABP领域层定义仓储并实现
    ABP领域层创建实体
    通过模板创建一个ABP项目
    Android UI组件:布局管理器
  • 原文地址:https://www.cnblogs.com/-mrl/p/15743618.html
Copyright © 2020-2023  润新知