首页 > 数据库 >神奇的 SQL 之 ICP → 索引条件下推

神奇的 SQL 之 ICP → 索引条件下推

时间:2022-11-03 12:35:06浏览次数:70  
标签:Index 下推 回表 索引 tbl SQL ICP

开心一刻

神奇的 SQL 之 ICP →  索引条件下推_回表

  楼主:来,我们先排练一遍

  小伙伴们:好

  嘿、哈、嚯

  楼主:非常好,就是这个节奏,我们开始吧

  楼主:啊、啊、啊,疼 ! 你们是不是故意的 ?

回表与覆盖索引

  正式讲 ICP 之前了,我们先将相关的概念捋一捋,知道的就当回顾,不知道的就当了解了,这有助于对 ICP 的理解

tbl_index
CREATE TABLE tbl_index (
c1 INT,
c2 INT,
c3 CHAR(1),
PRIMARY KEY(c1),
KEY idx_c2 (c2)
);

  覆盖索引

    如果 where 条件的列和 select 的列都在一个索引中,通过这个索引就可以完成查询,这就叫就叫覆盖索引;当然,覆盖索引基本针对的是组合索引(InnoDB 的聚簇索引有点特殊,具体可以看下面的图)

select c2 from tbl_index where c2 = 4; 是覆盖索引查询,但是这条 SQL 没有意义,如果我们在 tbl_index 表上增加索引 index ,那么 select c3 from tbl_index where c2 = 4;

  回表

    通过某个索引无法直接完成 SQL 查询(where 条件的列和 select 的列不全部存在于任何一个索引中),那么此时需要获取完整的数据记录来完成此次查询,从索引项记录到获取对应的完整数据记录的过程就叫回表;概念可能说的有些抽象,我们结合 MySQL 来看看具体什么是回表

    InnoDB 的回表

    InnoDB 的索引结构有些特殊,非聚簇索引(二级索引)回表到聚簇索引的过程类似如下

神奇的 SQL 之 ICP →  索引条件下推_ICP_02

select * from tbl_index where c1 = 10;

    MyISAM 的回表

MyISAM 中的索引都是二级索引

    MyISAM 聚簇索引和二级索引,以及它们的回表过程类似如下

神奇的 SQL 之 ICP →  索引条件下推_ICP_03

    MyISAM 的回表过程指的是根据叶子节点中的数据记录的地址来获取完整记录的过程,无论是聚簇索引还是二级索引都可能存在回表的过程;MyISAM 的回表与 InnoDB 还是有差别的

  无论是 InnoDB 的回表还是 MyISAM 的回表,很有可能会造成额外的磁盘 IO,这会严重影响查询效率,覆盖索引的目的就是尽量能够一次完成 SQL 查询,避免有回表过程,从而提高效率

  如何确认 MySQL 是进行了覆盖索引查询,还是进行了回表查询 ?

using index 则说明使用了覆盖索引查询,如果 Extra 中出现了 using index 或 using index & using where

ICP

  Index Condition Pushdown,MySQL 5.6 中引入的一种优化策略

  那么究竟是将什么从哪 Push Down 到哪,优化了什么?要弄清楚这 4 个问题,我们需要先弄清楚 where 条件的提取与应用,具体可查看:​​神奇的 SQL 之 WHERE 条件的提取与应用​​

Index Key,Index Filter,Table

  ICP 优化过程

tbl_icp

create table tbl_icp (a int primary key, b int, c int, d int, e varchar(50));
create index idx_bcd on tbl_icp(b, c, d);
insert into tbl_icp values (4,3,1,1,'a');
insert into tbl_icp values (1,1,1,2,'d');
insert into tbl_icp values (8,8,7,8,'h');
insert into tbl_icp values (2,2,1,2,'g');
insert into tbl_icp values (5,2,2,5,'e');
insert into tbl_icp values (3,3,2,1,'c');
insert into tbl_icp values (7,4,0,5,'b');
insert into tbl_icp values (6,5,2,4,'f');

View Code

    若没有使用 ICP,则 SQL 查询类似如下

神奇的 SQL 之 ICP →  索引条件下推_ICP_04

Index Key 范围限制的所有数据记录(示例中一共 6 条)逐条返回给 Server 层,然后由 server 层应用 Index Filter 和 Table

    若使用 ICP,则 SQL 查询类似如下

神奇的 SQL 之 ICP →  索引条件下推_sql_05

Index 下推到引擎层,引擎层在对 Index First Key 与 Index Last Key 范围内的索引项逐条进行过滤的时候,会应用上 Index Filter,对不满足 Index Filter 条件的索引项直接过滤掉,无需回表操作,也无需返回给 Server 层,从而提供执行效率;上图中的索引项: 3 1 1 、 3 2 1 不满足 Index Filter 中的 d != 1 , 4 0 5 不满足 c > 0

  相信到这里,大家对 ICP 的 4 个问题应该就比较清楚了

  ICP 的适用条件

    虽说 ICP 能提高 SQL 执行效率,但也不是任何情况下都适用的,它只适用于某些情况

    1、当 SQL 需要全表访问时,ICP 的优化策略可用于 range, ref, eq_ref,  ref_or_null 类型的数据访问方式

    2、只适用于 InnoDB 和 MyISAM 两种存储引擎

    3、在 InnoDB 中,ICP 只适用于二级索引

      ICP 的目的就是为了减少回表导致的磁盘 I/O,而 InnoDB 的聚簇索引的叶子节点存放的就是完整的数据记录,只要索引数据被读到内存了,那么索引项对应的完整数据记录也就读到内存了,那么通过索引项获取数据记录的过程就在内存中进行了,无需进行磁盘 I/O;也就说聚簇索引上应用 ICP,不会减少磁盘 I/O,也就没有使用的意义了

    4、不支持覆盖索引

      其实和第 3 点一样,因为覆盖索引无需回表,ICP 也就没意义了

    5、不支持子查询条件的下推

    6、不支持存储过程条件、触发器条件的下推

  至于 ICP 的优化效果,取决于在存储引擎内通过 ICP 筛选掉的数据的比例,过滤掉的数据比例大,那就性能提升大,反之则性能提升小

总结

  1、索引覆盖与回表

    这两个往往是一起来考虑的,因为覆盖索引的目的就是减少因回表产生的磁盘 I/O,从而提高执行效率

    在实际应用中,我们往往也需要考虑尽可能用覆盖索引来完成我们的 SQL 查询

  2、ICP的四个问题

    将什么从哪 Push Down 到哪,优化了什么

    将 Index Filter 从 Server 层 Push Down 到了引擎层,减少了因回表产生的磁盘 I/O,也减少了与 Server 层的交互,提高了 SQL 执行效率

  3、疑问点

    为什么这么明显的优化策略到 MySQL 5.6 才引入,个人感觉很容易就能考虑到呀,MySQL 的开发者们是肿么肥事 ?

神奇的 SQL 之 ICP →  索引条件下推_sql_06

    可能是楼主在巨人的肩膀上,站着说话不腰疼吧......

参考

  ​​Index Condition Pushdown Optimization​

  ​​Index Condition Pushdown​

  ​​MySQL的索引​



标签:Index,下推,回表,索引,tbl,SQL,ICP
From: https://blog.51cto.com/u_13423706/5819390

相关文章

  • mysql忘记密码如何修改密码
    1、修改mysql配置文件,在文件最后加上skip-grant-tables2、重启mysql,这里必须重启mysql配置才生效3、使用mysql-uroot-p登录mysql,登录时不需要输入密码4、登录后使......
  • postgresql闪回查询及其问题
    其实早在2018年,PostgresProfessional就实现了一个闪回查询的原型,基于vacuum_defer_cleanup_age和track_commit_timestamp。这本质上和LZ所想一致。但是存在的问题是膨胀......
  • mysql 部分计算调拨逻辑
    selectt4.sp码,t4.zaituas'在途',t4.仓库名称AS'中心仓',t4.标品名称,t4.库存成本,t4.货主,t4.分类名称,t4.一级分类名称,t4.库存数量as'中心仓库存',t4.......
  • SQLServer 还原数据库时提示占用
    --还原数据库提示“因为数据库正在使用,所以无法获得对数据库的独占访问权。--首先选中master数据库,执行以下语句declare@dbnamevarchar(50)set@dbname='mzysgzz'decla......
  • MySQL生成连续的数
    背景MySQL版本5.7,需要生成连续的日期,只通过select,而不走自定义函数或存储过程思路只需要生成连续的数字,然后通过日期时间函数操作即可脚本SELECT DATE_ADD......
  • MySQL 忘记密码
    关闭正在运行的mysql服务以安全模式启动mysqlmysqld--shared-memory--skip-grant-tables--console使用另一个命令行连接mysql数据库。无需输入密码,直接回车跳过......
  • 查看mysql资源使用情况
    usesysselectevent_name,current_allocfromsys.memory_global_by_current_byteslimit10;selecthost,current_allocatedfrommemory_by_host_by_current_byte......
  • PostgreSQL 磁盘空间清理
    PostgreSQL磁盘空间清理背景PostgreSQL删除、更新、覆写的历史数据不会从磁盘中清除,久而久之,磁盘的数据越来越多造成空间不足。解决方案定期找到空间占用大的表,然后......
  • sqlserver查询语句SELECT
    SELECT查询语句数据查询是数据库的核心操作,其功能是指根据用户的需要从数据库中提取所需数据,通过SQL的数据操纵语言的SELECT语句可以实现数据库数据的查询。SELECT语句是......
  • MySQL如何保证数据一致性
    如何保证一致性数据库通过原子性(A)、隔离性(I)、持久性(D)来保证一致性(C)。其中一致性是目的,原子性、隔离性、持久性是手段。因此数据库必须实现AID三大特性才有可能实现一致性......