首页 > 数据库 >MySql索引下推知识分享

MySql索引下推知识分享

时间:2022-12-22 11:05:21浏览次数:67  
标签:存储 下推 回表 索引 引擎 MySql ICP

作者:刘邓忠

Mysql是大家最常用的数据库,下面为大家带来mysql索引下推知识点的分享,以便巩固mysql基础知识,如有错误,还请各位大佬们指正。

1 什么是索引下推

索引下推(Index Condition Pushdown,索引条件下推,简称ICP),是MySQL5.6版本的新特性,它可以在对联合索引遍历过程中,对索引中包含的所有字段先做判断,过滤掉不符合条件的记录之后再回表,能有效的减少回表次数(目前我们使用的mysql版本较高,一般大家可能感觉这是正常的,但是mysql5.6之前都不是这样实现的,下面会细细道来)。

1.1 适用条件

我们先来了解一下索引下推的使用条件及限制:

  • 只支持select。
  • 当需要访问全表时,ICP用于range,ref,eq_ref和ref_or_null访问类型。
  • ICP可用于InnoDB和MyISAM表,包括分区的InnoDB和MyISAM表。(5.6版本不适用分区表查询,5.7版本后可以用于分区表查询)。
  • 对于InnDB引擎只适用于二级索引(也叫辅助索引),因为InnDB的聚簇索引会将整行数据读到InnDB的缓冲区,这样一来索引条件下推的主要目的减少IO次数就失去了意义。因为数据已经在内存中了,不再需要去读取了。
  • 在虚拟生成列上创建的辅助索引不支持ICP(注:InnoDB支持虚拟生成列的辅助索引)。
  • 使用了子查询的条件无法下推。
  • 使用存储过程或函数的条件无法下推(因为因为存储引擎没有调用存储过程或函数的能力)。
  • 触发条件无法下推。(有关触发条件的信息,请参阅官方资料:Section 8.2.2.3, “Optimizing Subqueries with the EXISTS Strategy”.。)

1.2 原理介绍

首先,我们大致回顾下mysql的基本架构:

MySql索引下推知识分享_主键



MySQL基本的架构示例图

MySQL服务层主要负责SQL语法解析、生成执行计划等,并调用存储引擎层去执行数据的存储和查询。

索引下推的下推其含义就是指将部分上层(服务层)负责的事情,交给了下层(引擎层)去处理。

在 MySql 5.6 版本之前没有索引下推这个功能,从 5.6 版本后才加上了这个优化项。我们先简单对比一下使用和未使用ICP两种情况下,MySql的查询过程吧。


1)未使用ICP的情况下:

- 存储引擎读取索引记录;

- 根据索引中的主键值,定位并读取完整的行记录;

- 存储引擎把记录交给Server层去检测该记录是否满足WHERE条件。


2)使用ICP的情况下:

- 存储引擎读取索引记录(不是完整的行记录);

- 判断WHERE条件部分能否用索引中的列来做检查,条件不满足,则处理下一行索引记录;

- 条件满足,使用索引中的主键去定位并读取完整的行记录(就是所谓的回表);

- 存储引擎把记录交给Server层,Server层检测该记录是否满足WHERE条件的其余部分。


2 具体示例

上面介绍了基本原理,下面使用示例,带大家更直观的进行理解(注:以下示例基于InnoDB存储引擎。)

首先,我们新建一张用户表(jxc_user),设置id为主键索引,并创建联合索引(name, age)。


MySql索引下推知识分享_MySQL_02



我们先看一下该表主键索引的大致结构示例:


MySql索引下推知识分享_联合索引_03

主键索引结构示例图

然后我们再看一下该表联合索引的大致结构示例:


MySql索引下推知识分享_联合索引_04

联合索引结构示例图

如果现在有一个需求,要求检索出表中名字第一个字是张,而且年龄等于10岁的所有用户。示例SQL语句如下:

select id,name,age,tel,addr from jxc_user where name like '张%' and age=10;

根据索引最左匹配原则,上面这个sql语句在查索引树的时候,只能用“张”,查到第一个满足条件的记录:id为1。
那接下来我们具体看一下 使用与未使用ICP的情况。

2.1 未使用ICP的情况

在MySQL 5.6之前,存储引擎根据联合索引先找到name like ‘张%’ 的主键id(1、4),再逐一进行回表扫描,去聚簇索引找到完整的行记录,返回server层,server层拿到数据后,再根据条件age=10对拿到的数据进行筛选。大致的示意图如下:

MySql索引下推知识分享_MySQL_05

从上图,可以看到需要回表两次,存储引擎并不会去按照age=10进行过滤,相当于联合索引的另一个字段age在存储引擎层没有发挥作用,比较浪费。

2.2 使用ICP的情况

而MySQL 5.6 以后, 存储引擎会根据(name,age)联合索引,找到name like ‘张%’,由于联合索引中包含age列,所以存储引擎直接再联合索引里按照条件age=10进行过滤,然后根据过滤后的数据再依次进行回表扫描。大致的示意图如下:

MySql索引下推知识分享_索引下推_06

从上图,可以看到只是id=1的数据,回表了一次。

除此之外我们还可以看一下执行计划,看到Extra一列里Using index condition,就是用到了索引下推。

MySql索引下推知识分享_主键_07

3 控制参数

Mysql索引下推功能默认是开启的,可以用系统参数optimizer_switch来控制是否开启。
查看状态命令:
select @​​@optimizer_switch​​;

MySql索引下推知识分享_MySQL_08

关闭命令:set optimizer_switch=”index_condition_pushdown=off”;
开启命令:set optimizer_switch=”index_condition_pushdown=on”;

4 总结

回表操作:当所要查找的字段不在非主键索引树上时,需要通过叶子节点的主键值去主键索引上获取对应的行数据,这个过程称为回表操作。
索引下推:索引下推主要是减少了不必要的回表操作。对于查找出来的数据,先过滤掉不符合条件的,其余的再去主键索引树上查找。

5 参考文献


标签:存储,下推,回表,索引,引擎,MySql,ICP
From: https://blog.51cto.com/u_15714439/5962406

相关文章

  • mysql 字段名为 timestamp ,不让转义
    select ip_type'IP类型', timestamp'数据填报时间'from ( select d.id, if(d.ip_type=0, 'IP', 'IP段')ip_type, d.timestamp, (CASE d.visibl......
  • postgresql jsonb + 索引 + 分区 + 测试
    --创建表DROPTABLEIFEXISTStba;CREATETABLEtba(idserial,peaktempint,jsjsonb,logdatedatenotnull)PARTITIONBYRANGE(logdate); --设置主键......
  • 一个MySQL双引号把我坑惨了!
    一、前言 最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程,把我坑得够惨。 二、过程 由于开发需要在生产环节中修复数据,需要执行120......
  • MySQL8.0新特性--基于Write Set并行复制
    复制简介MySQL早期只有单线程复制,即IO线程接收master的binlog,并写入本地的relaylog中,SQL线程负责从relaylog中服务event并进行apply。当主库的写入压力较大时,备库的IO线......
  • MySQL8.0新特性--Clone Plugin克隆
    ClonePlugin简介8.0.17引入cloneplugin,允许从本地或者远程的MySQL中克隆数据克隆的数据包括schema、表、表空间、元数据等等,克隆的数据是一个完整的数据目录,插件可以使......
  • MySQL8.0新特性--使用SQL管理undo表空间
    8.0之前的undotablespaces管理InnoDB的undolog最主要是存储回滚数据,是实现MVCC的重要组件;innodb的一个rollbacksegment分为1024个undologsegment,即最大支持1024个并......
  • MySQL8.0新特性--新数据字典
    一、简介数据字典(DataDictionary),存储数据库的元数据信息,如database、table、index、column等。由于MySQL数据库是插件式数据库,分为SERVER层和存储引擎层,存储引擎层可以......
  • MySQL8.0新特性-原子DDL
    MySQL8.0以前的DDLDDL(DataDefinitionLanguage)定义了数据在数据库中的结构、关系以及权限等,比如CREATE、ALTER、DROP、GRANT等等。在MySQL8.0之前的版本中,由于架构的原......
  • MySQL中这14个牛逼的功能,惊艳到我了!!!
    MySQL中这14个牛逼的功能,惊艳到我了!!! 前言我最近几年用MYSQL数据库挺多的,发现了一些非常有用的小玩意,今天拿出来分享到大家,希望对你会有所帮助。1.group_concat在我......
  • MySQL之使用pt-online-schema-change在线修改大表结构
    原因:最近公司上一个功能,需要为其中某个表中新增字段,但是考虑到线上数据已经达到300w+的级别,同时使用的mysql的版本是5.7而非8.0,这会导致新增字段的时候,对全表进行......