执行一条select语句,mysql会发生什么

基础篇:

执行一条select语句,mysql会发生什么

连接器----> server 层 ----> 引擎层

server层:

查询缓存(8.0 就删除了) ---->解析器(语义,语法 )----> 预处理器 ----> 优化器 ----> 执行计划 ----> 执行器

索引

索引覆盖和索引下推的理解:

目的都是为了回表,而且都是对于联合索引来说。

索引覆盖是通过 联合索引中包含了所有的需要查询的字段 减少回表。

比如:

索引下推 首先说明对索引的使用不起决定作用,只是通过存储引擎层进行数据的过滤,减少回表次数。【见下面Explain里面有一个索引下推的案例】

例如:现在有一张表,联合索引是(className,address)

CREATE TABLE `class`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `className` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `address` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `monitor` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_classname_add`(`className`, `address`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10000 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

通过执行计划,我们可以看到,这里使用了联合索引,但是其实只有 className 起作用,key_len = 30*3 +1+2;其实这里看where后面的查询条件,是不满足联合索引最左匹配原则的,但是优化器会优化顺序,优化为 className = “xxx” and address like ‘%s’ ,这样就解释了为什么用到了联合索引中的className字段;又因为like 的 ‘%S’ 会导致索引失效,所以无法使用address字段,**但是索引下推还是会帮忙在引擎层过滤数据,**最后通过server回表查询 所需要的字段。

技术分享 | EXPLAIN 执行计划详解(2)–Extra - 知乎 (zhihu.com)

五分钟搞懂MySQL索引下推 - 掘金 (juejin.cn)

funnylog.gitee.io/mysql45/05讲深入浅出索引(下).html

[java面试一日一题:mysql的索引下推了解吗 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/371868151#:~:text=索引下推是在非主键索引,或者说二级索引%2F联合索引的情形下,索引的匹配规则遵循最左原则,最左原则会因为like或范围判断而后面的索引失效,这时在mysql5.6后引入了索引下推的概念,来优化查询效率。 例,select id%2Cname%2Cage from student,where name like ‘张%’ and age%3D32%3B)

Explain

tpye

  • 当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法就是 const
  • 当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是 ref
  • 如果使用索引获取某些 范围区间 的记录,那么就可能使用到 range 访问方法,between,> ,like ‘X%’
  • 当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是 index
  • all 最熟悉的全表扫描

extra

  • Using index

当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以使用索引覆盖的情况下,在Extra 列将会提示该额外信息。比方说下边这个查询中只需要用到 idx_key1 而不需要回表操作:

  • Using index condition

些搜索条件中虽然出现了索引列,但却不能使用到索引,比如下边这个查询:

SELECT * FROM s1 WHERE key1 > ‘z’ AND key1 LIKE ‘%a’;

其中的 key1 > ‘z’ 可以使用到索引,但是 key1 LIKE ‘%a’ 却无法使用到索引,在以前版本的 MySQL 中,

是按照下边步骤来执行这个查询的:

  • 先根据 key1 > ‘z’ 这个条件,从二级索引 idx_key1 中获取到对应的二级索引记录。

  • 根据上一步骤得到的二级索引记录中的主键值进行回表,找到完整的用户记录再检测该记录是否符合key1 LIKE ‘%a’ 这个条件,将符合条件的记录加入到最后的结果集。但是虽然 key1 LIKE ‘%a’ 不能组成范围区间参与 range 访问方法的执行,但这个条件毕竟只涉及到了key1 列,所以设计 MySQL 的大叔把上边的步骤改进了一下:

    • 先根据 key1 > ‘z’ 这个条件,定位到二级索引 idx_key1 中对应的二级索引记录。

    • 对于指定的二级索引记录,先不着急回表,而是先检测一下该记录是否满足 key1 LIKE ‘%a’ 这个条件,如果这个条件不满足,则该二级索引记录压根儿就没必要回表。

    • 对于满足 key1 LIKE ‘%a’ 这个条件的二级索引记录执行回表操作。

我们说回表操作其实是一个随机 IO ,比较耗时,所以上述修改虽然只改进了一点点,但是可以省去好

多回表操作的成本。设计 MySQL 的大叔们把他们的这个改进称之为 索引条件下推 (英文名: Index

Condition Pushdown )。

如果在查询语句的执行过程中将要使用 索引条件下推 这个特性,在 Extra 列中将会显示 Using index

condition

  • Using where

当我们使用全表扫描来执行对某个表的查询,并且该语句的 WHERE 子句中有针对该表的搜索条件时

示 Using index

condition

  • Using where

当我们使用全表扫描来执行对某个表的查询,并且该语句的 WHERE 子句中有针对该表的搜索条件时

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值