MySQL 回表,覆盖索引,索引下推

 更新时间:2022年07月11日 08:48:54   作者:向着百万年薪努力的小  
这篇文章主要介绍了MySQL 回表,覆盖索引,索引下推,就是我们需要查询的数据都在二级索引树中,直接返回这种情况就叫做覆盖索引

回表

在研究mysql二级索引的时候,发现Mysql回表这个操作,往下研究了一下

字面意思,找到索引,回到表中找数据

解释一下就是:

先通过索引扫描出数据所在的行,再通过行主键ID 取出数据。

举个例子说明:

SELECT * FROM INNODB_USER
WHERE AGE = 18 AND USER_NAME LIKE '模糊查%';

假如ageuser_name两个字段是个联合索引,我们通过age=18这个索引找到了二级索引树对应页所在的数据,但是由于user_name是模糊查询,导致了这个字段的索引失效,我们得到了二级索引的这一页中age=18的很多个数据(主键id),我们通过这些主键ID回到主键索引树里再查表里的数据,这个操作就是回表。

另外回表的产生也是需要一定条件的,如果一次索引查询就能获得所有的select 记录(也就是联合索引已经包含了你查的字段)就不需要回表,如果select 所需获得列中有其他的非索引列,就会发生回表动作。即基于非主键索引的查询需要多扫描一棵索引树。

另外上面所说的不需要回表,其实还有另一个名词

覆盖索引

就是我们需要查询的数据都在二级索引树中,直接返回这种情况就叫做覆盖索引。

上面提到的联合索引、二级索引树、主键索引树这些名词,如果同学们还没有啥概念,请看我写的这一篇文章,详细介绍了MYSQL的索引
链接: MySQL索引详解及演进过程及面试题延伸

索引下推

索引下推(index condition pushdown )简称ICP,在Mysql5.6以后的版本上推出,用于优化回表查询;

在不使用ICP的情况下,在使用非主键索引(又叫普通索引或者二级索引)进行查询时,存储引擎通过索引检索到数据,然后返回给MySQL服务器,服务器然后判断数据是否符合条件 ;

在使用ICP的情况下,如果存在某些被索引的列的判断条件时,MySQL服务器将这一部分判断条件传递给存储引擎,
然后由存储引擎通过判断索引是否符合MySQL服务器传递的条件,只有当索引符合条件时才会将数据检索出来返回给MySQL服务器 ;

索引条件下推优化可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数。

举个栗子:

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(64) NOT NULL COMMENT '用户名 ',
  `age` int(8) NOT NULL COMMENT '年纪',
	`address` varchar(255) DEFAULT NULL COMMENT '地址',
  `is_delete` tinyint NOT NULL DEFAULT '0' COMMENT '是否删除 默认否',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `idx_name_age` (`name`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户信息表';
-- 初始化数据 
INSERT INTO `t_user`(`name`, `age`, `address`) VALUES ('李四', 22, '中国');
INSERT INTO `t_user`(`name`, `age`, `address`) VALUES ('李五', 22, '中国');
INSERT INTO `t_user`(`name`, `age`, `address`) VALUES ('李六', 23, '中国');
INSERT INTO `t_user`(`name`, `age`, `address`) VALUES ('张三', 24, '中国');
INSERT INTO `t_user`(`name`, `age`, `address`) VALUES ('李期', 24, '中国');

用上面的语句建一个测试用的表

无索引下推: 查看索引下推的状态

show VARIABLES like '%optimizer_switch%';
-------------------------------------------------------
optimizer_switch	index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on,use_invisible_indexes=off,skip_scan=on,hash_join=on,subquery_to_derived=off,prefer_ordering_index=on,hypergraph_optimizer=off,derived_condition_pushdown=on

关闭索引下推:

索引下推是mysql 5.6优化查询回表的功能,在5.6之前都不支持索引下推,笔者用的8.0,则需要先关闭索引下推:
set optimizer_switch='index_condition_pushdown=off';

执行sql;

EXPLAIN SELECT * from t_user where name like '李%' and age = 22;

在这里插入图片描述

分析一下以上sql执行的过程:

  • 1. idx_name_age`组合索引 遵循最左匹配遇到非等值判断时匹配停止,name的范围查询则会使age这个条件就不会走索引;
  • 2. 会先在name索引上顺序找到 符合条件的name和id数据;
  • 3. 然后通过id在聚簇索引上回表找到对应的age数据,将结果存放在临时表中;
  • 4. 最后在临时表中通过age条件来筛选数据。

以上过程会扫描4条记录,回表4次。
extra = Using where:表示优化器需要通过索引回表查询数据。

有索引下推: 开启索引下推

set optimizer_switch='index_condition_pushdown=on';

执行sql:

EXPLAIN SELECT * from t_user where name like '李%' and age = 22;

在这里插入图片描述

开启索引下推优化后再分析一下以上sql执行的过程:

  • 1. 由于开启了索引下推会在idx_name_age索引上同时检索满足name和age的条件的数据的id;
  • 2. 再用id到聚簇索引上查询完整的数据。

以上过程会扫描4行数据,回表次数是2次。

extra = Using index condition 表示索引下推。

总结:

  • 索引下推功能是mysql 5.6推出优化回表的操作,只支持向上兼容,低版本是不支持的;
  • 索引下推优化的只是回表次数,扫描行数还是一样的。

到此这篇关于MySQL 回表,覆盖索引,索引下推的文章就介绍到这了,更多相关MySQL 回表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 总结三道MySQL联合索引面试题

    总结三道MySQL联合索引面试题

    这篇文章主要介绍了总结三道MySQL联合索引面试题,众所周知MySQL联合索引遵循最左前缀匹配原则,在少数情况下也会不遵循,创建联合索引的时候,建议优先把区分度高的字段放在第一列
    2022-08-08
  • mysql中使用sql命令将时间戳解析成datetime类型存入

    mysql中使用sql命令将时间戳解析成datetime类型存入

    这篇文章主要介绍了mysql中使用sql命令将时间戳解析成datetime类型存入,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • CentOS系统下MySQL彻底卸载的几种方法

    CentOS系统下MySQL彻底卸载的几种方法

    在CentOS系统中,我们可以使用多种方法来卸载MySQL软件包,这篇文章主要给大家介绍了关于CentOS系统下MySQL彻底卸载的几种方法,文中通过代码示例将每种方法都介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • 详解让MySQL和Redis数据保持一致的四种策略

    详解让MySQL和Redis数据保持一致的四种策略

    在分布式系统中,保证Redis和MySQL之间的数据一致性是一个复杂且重要的问题,下面这篇文章主要给大家介绍了关于让MySQL和Redis数据保持一致的四种策略,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • MySQL常用登录命令小结

    MySQL常用登录命令小结

    本文主要介绍了MySQL常用登录命令小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • 基于mysql体系结构的深入解析

    基于mysql体系结构的深入解析

    本篇文章是对mysql体系结构进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Mysql实现递归树查询的使用示例

    Mysql实现递归树查询的使用示例

    Mysql我们可以使用递归查询来构建一个递归树,本文就来介绍一下Mysql实现递归树查询的使用示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • win32 mysql 5.7.27 安装配置方法图文教程

    win32 mysql 5.7.27 安装配置方法图文教程

    这篇文章主要为大家详细介绍了win32 mysql 5.7.27 安装配置方法图文教程,文中安装步骤介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • Mysql如何获取json字符串/数组的值

    Mysql如何获取json字符串/数组的值

    这篇文章主要介绍了Mysql如何获取json字符串/数组的值问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • MySQL group by和left join并用解决方式

    MySQL group by和left join并用解决方式

    这篇文章主要介绍了MySQL group by和left join并用解决方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12

最新评论