MySQL 回表,覆盖索引,索引下推 |
回表在研究mysql二级索引的时候,发现Mysql回表这个操作,往下研究了一下 字面意思,找到索引,回到表中找数据 解释一下就是:
举个例子说明: SELECT * FROM INNODB_USER WHERE AGE = 18 AND USER_NAME LIKE '模糊查%'; 假如 另外回表的产生也是需要一定条件的,如果一次索引查询就能获得所有的select 记录(也就是联合索引已经包含了你查的字段)就不需要回表,如果select 所需获得列中有其他的非索引列,就会发生回表动作 。即基于非主键索引的查询需要多扫描一棵索引树 。 另外上面所说的不需要回表,其实还有另一个名词 覆盖索引就是我们需要查询的数据都在二级索引树中,直接返回这种情况就叫做覆盖索引 。 上面提到的联合索引、二级索引树、主键索引树这些名词,如果同学们还没有啥概念,请看我写的这一篇文章,详细介绍了MYSQL的索引 索引下推索引下推(index condition pushdown )简称ICP,在Mysql5.6以后的版本上推出,用于优化回表查询; 在不使用ICP的情况下,在使用非主键索引(又叫普通索引或者二级索引)进行查询时,存储引擎通过索引检索到数据,然后返回给MySQL服务器,服务器然后判断数据是否符合条件 ; 在使用ICP的情况下,如果存在某些被索引的列的判断条件时,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执行的过程:
以上过程会扫描4条记录,回表4次 。 有索引下推: 开启索引下推set optimizer_switch='index_condition_pushdown=on'; 执行sql: EXPLAIN SELECT * from t_user where name like '李%' and age = 22; 开启索引下推优化后再分析一下以上sql执行的过程:
以上过程会扫描4行数据,回表次数是2次 。 extra = Using index condition 表示索引下推 。 总结:
到此这篇关于MySQL 回表,覆盖索引,索引下推的文章就介绍到这了,更多相关MySQL 回表内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持! |