专业游戏门户,分享手游网游单机游戏百科知识攻略!

嗨游网
嗨游网

一文搞懂MySQL索引下推

来源:小嗨整编  作者:小嗨  发布时间:2024-03-21 07:23
摘要:本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于索引下推的相关内容,索引条件下推也叫索引下推,英文全称indexconditionpushdown,简称icp,用于优化数据查询,下面一起来看一下,希望对大家有帮助。推荐学...

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于索引下推的相关内容,索引条件下推也叫索引下推,英文全称index condition pushdown,简称icp,用于优化数据查询,下面一起来看一下,希望对大家有帮助。

一文搞懂MySQL索引下推

推荐学习:mysql视频教程

SELECT 语句执行过程

MySQL 数据库由 Server 层和 Engine 层组成:

Server 层:SQL 分析器、SQL 优化器、SQL 执行器,用于负责 SQL 语句的具体执行过程。Engine 层: 负责存储具体的数据,如最常使用的 InnoDB 存储引擎,还有用于在内存中存储临时结果集的 TempTable 引擎。

通过客户端/服务器通信协议与 MySQL 建立连接。

查询缓存:

如果开启了 Query Cache 且在查询缓存过程中查询到完全相同的 SQL 语句,则将查询结果直接返回给客户端;如果没有开启 Query Cache 或者没有查询到完全相同的 SQL 语句则会由解析器进行语法语义解析,并生成解析树。

分析器生成新的解析树。

查询优化器生成执行计划。

查询执行引擎执行 SQL 语句,此时查询执行引擎会根据 SQL 语句中表的存储引擎类型,以及对应的 API 接口与底层存储引擎缓存或者物理文件的交互情况,得到查询结果,由 MySQL Server 过滤后将查询结果缓存并返回给客户端。

若开启了 Query Cache,这时也会将 SQL 语句和结果完整地保存到 Query Cache 中,以后若有相同的 SQL 语句执行则直接返回结果。

TipsMySQL 8.0 已去掉 query cache(查询缓存模块)。

因为查询缓存的命中率会非常低。 查询缓存的失效非常频繁:只要有对一个表的更新,这个表上所有的查询缓存都会被清空。

什么是索引下推?

索引下推(Index Condition Pushdown): 简称 ICP,通过把索引过滤条件下推到存储引擎,来减少 MySQL 存储引擎访问基表的次数 和 MySQL 服务层访问存储引擎的次数。

索引下推 VS 覆盖索引: 其实都是 减少回表的次数,只不过方式不同

覆盖索引: 当索引中包含所需要的字段(SELECT XXX),则不再回表去查询字段。

索引下推: 对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表的行数。

要了解 ICP 是如何工作的,先从一个查询 SQL 开始:

举个栗子:查询名字 la 开头、年龄为 18 的记录

SELECT * FROM user WHERE name LIKE 'la%' AND age = 18;
登录后复制

有这些记录:

不开启 ICP 时索引扫描是如何进行的:

通过索引元组,定位读取对应数据行。(实际上:就是回表)对 WHERE 中字段做判断,过滤掉不满足条件的行。

使用 ICP,索引扫描如下进行:

获取索引元组。对 WHERE 中字段做判断,在索引列中进行过滤。对满足条件的索引,进行回表查询整行。对 WHERE 中字段做判断,过滤掉不满足条件的行。

动手实验:

实验:使用 MySQL 版本 8.0.16

-- 表创建CREATE TABLE IF NOT EXISTS `user` (`id` VARCHAR(64) NOT NULL COMMENT '主键 id',`name` VARCHAR(50) NOT NULL COMMENT '名字',`age` TINYINT NOT NULL COMMENT '年龄',`address` VARCHAR(100) NOT NULL COMMENT '地址',PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT '用户表';-- 创建索引CREATE INDEX idx_name_age ON user (name, age);-- 新增数据INSERT INTO user (id, name, age, address) VALUES (1, 'tt', 14, 'linhai');INSERT INTO user (id, name, age, address) VALUES (2, 'lala', 18, 'linhai');INSERT INTO user (id, name, age, address) VALUES (3, 'laxi', 30, 'linhai');INSERT INTO user (id, name, age, address) VALUES (4, 'lawa', 40, 'linhai');-- 查询语句SELECT * FROM user WHERE name LIKE 'la%' AND age = 18;
登录后复制

新增数据如下:

关闭 ICP,再调用 EXPLAIN 查看语句:
-- 将 ICP 关闭SET optimizer_switch = 'index_condition_pushdown=off';-- 查看确认show variables like 'optimizer_switch';-- 用 EXPLAIN 查看EXPLAIN SELECT * FROM user WHERE name LIKE 'la%' AND age = 18;
登录后复制

开启 ICP,再调用 EXPLAIN 查看语句:
-- 将 ICP 打开SET optimizer_switch = 'index_condition_pushdown=on';-- 查看确认show variables like 'optimizer_switch';-- 用 EXPLAIN 查看EXPLAIN SELECT * FROM user WHERE name LIKE 'la%' AND age = 18;
登录后复制

由上实验可知,区别是否开启 ICP Exira 字段中的 Using index condition

更进一步,来看下 ICP 带来的性能提升:

通过访问数据文件的次数

-- 1. 清空 status 状态flush status;-- 2. 查询SELECT * FROM user WHERE name LIKE 'la%' AND age = 18;-- 3. 查看 handler 状态show status like '%handler%';
登录后复制

对比开启 ICP 和 关闭 ICP 关注 Handler_read_next 的值

-- 开启 ICPflush status;SELECT * FROM user WHERE name LIKE 'la%' AND age = 18;show status like '%handler%';+----------------------------|-------+| Variable_name              | Value |+----------------------------|-------+| Handler_commit             | 1     || Handler_delete             | 0     || Handler_discover           | 0     || Handler_external_lock      | 2     || Handler_mrr_init           | 0     || Handler_prepare            | 0     || Handler_read_first         | 0     || Handler_read_key           | 1     |  | Handler_read_last          | 0     || Handler_read_next          | 1     |  <---重点| Handler_read_prev          | 0     || Handler_read_rnd           | 0     || Handler_read_rnd_next      | 0     || Handler_rollback           | 0     || Handler_savepoint          | 0     || Handler_savepoint_rollback | 0     || Handler_update             | 0     || Handler_write              | 0     |+----------------------------|-------+18 rows in set (0.00 sec)-- 关闭 ICPflush status;SELECT * FROM user WHERE name LIKE 'la%' AND age = 18;show status like '%handler%';+----------------------------|-------+| Variable_name              | Value |+----------------------------|-------+| Handler_commit             | 1     || Handler_delete             | 0     || Handler_discover           | 0     || Handler_external_lock      | 2     || Handler_mrr_init           | 0     || Handler_prepare            | 0     || Handler_read_first         | 0     || Handler_read_key           | 1     || Handler_read_last          | 0     || Handler_read_next          | 3     |  <---重点| Handler_read_prev          | 0     || Handler_read_rnd           | 0     || Handler_read_rnd_next      | 0     || Handler_rollback           | 0     || Handler_savepoint          | 0     || Handler_savepoint_rollback | 0     || Handler_update             | 0     || Handler_write              | 0     |+----------------------------|-------+18 rows in set (0.00 sec)
登录后复制

由上实验可知:

开启 ICPHandler_read_next 等于 1,回表查 1 次。关闭 ICPHandler_read_next 等于 3,回表查 3 次。

这实验跟上面的栗子就对应上了。

索引下推限制

根据官网可知,索引下推 受以下条件限制:

当需要访问整个表行时,ICP 用于 rangerefeq_refref_or_null

ICP可以用于 InnoDBMyISAM 表,包括分区表 InnoDBMyISAM 表。

对于 InnoDB 表,ICP 仅用于二级索引。ICP 的目标是减少全行读取次数,从而减少 I/O 操作。对于 InnoDB 聚集索引,完整的记录已经读入 InnoDB 缓冲区。在这种情况下使用 ICP 不会减少 I/O

在虚拟生成列上创建的二级索引不支持 ICPInnoDB 支持虚拟生成列的二级索引。

引用子查询的条件不能下推。

引用存储功能的条件不能被按下。存储引擎不能调用存储的函数。

触发条件不能下推。

不能将条件下推到包含对系统变量的引用的派生表。(MySQL 8.0.30 及更高版本)。

小结下:

ICP 仅适用于 二级索引ICP 目标是 减少回表查询ICP 对联合索引的部分列模糊查询非常有效。拓展:虚拟列
CREATE TABLE UserLogin (userId BIGINT,loginInfo JSON,cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone"),PRIMARY KEY(userId),UNIQUE KEY idx_cellphone(cellphone));
登录后复制

cellphone :就是一个虚拟列,它是由后面的函数表达式计算而成,本身这个列不占用任何的存储空间,而索引 idx_cellphone 实质是一个函数索引

好处: 在写 SQL 时可以直接使用这个虚拟列,而不用写冗长的函数。

举个栗子: 查询手机号

-- 不用虚拟列SELECT * FROM UserLogin WHERE loginInfo->>"$.cellphone" = '13988888888'-- 使用虚拟列SELECT * FROM UserLogin WHERE cellphone = '13988888888'
登录后复制

推荐学习:mysql视频教程

以上就是一文搞懂MySQL索引下推的详细内容,更多请关注易企推科技其它相关文章!


本文地址:网络百科频道 https://www.eeeoo.cn/wangluo/1151729.html,嗨游网一个专业手游免费下载攻略知识分享平台,本站部分内容来自网络分享,不对内容负责,如有涉及到您的权益,请联系我们删除,谢谢!


网络百科
小编:小嗨整编
相关文章相关阅读
  • mysql安装教程图解(mysql安装教程最新)

    mysql安装教程图解(mysql安装教程最新)

    mysql安装教程图解(mysql安装教程最新)MySQL是当前最流行的关系型数据库管理系统之一,在Web应用方面MySQL是最好的RDBMS(RelationalDatabaseManagementSystem:关系数据库管理系统)应用软...

  • mysql中的不等于符号是什么

    mysql中的不等于符号是什么

    mysql中的不等于符号有两种:“!=”和“”;它们都可用于判断数字、字符串、表达式是否不相等。对于“!=”和“”,如果两侧操作数不相等,返回值为1,否则返回值为0;如果两侧操作数有一个是null,那么返回值也是null。本教程操作环境:w...

  • mysql列转行函数是什么

    mysql列转行函数是什么

    在mysql中,列转行函数是“group_concat()”函数;该函数用于将非空列值按照分组条件进行合并并最终返回,如果其中有空值则返回的结果是空,语法为“selectgroup_concat(name separator';')列...

  • MySQL连接被重置,如何处理?

    MySQL连接被重置,如何处理?

    mysql连接被重置,如何处理?MySQL是一种常用的关系型数据库管理系统,广泛应用于各种不同规模的项目中。然而,在使用MySQL时,有时会遇到连接被重置的情况,这可能会给我们的项目带来一些麻烦。本文将介绍MySQL连接被重置的原因以及如何...

  • 带你搞懂git回滚代码(实例详解)

    带你搞懂git回滚代码(实例详解)

    本篇文章给大家带来了关于git回滚代码的相关知识,git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理,希望对大家有帮助。在日常coding的过程中免不了分支之间的合并,回滚、提交、打tag等操作,如果你现...

  • mysql环境变量如何配置

    mysql环境变量如何配置

    mysql环境变量的配置方法:1、找到c盘中的mysql安装路径;2、在“我的电脑"中,依次点击“系统属性”-“高级系统设置”选项;3、在“环境变量”弹窗中,依次点击“高级”-“系统变量”;4、找到path路径,点击“编辑”选项,......

  • mysql查询怎么设置降序

    mysql查询怎么设置降序

    在mysql中,可以利用desc关键字对查询结果进行降序显示,该关键字是descend的缩写,常于orderby子句配合使查询结果降序,语法为“select字段1,字段2...from表名orderby指定字段desc”。本...

  • 一文搞懂MySQL索引下推

    一文搞懂MySQL索引下推

    本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于索引下推的相关内容,索引条件下推也叫索引下推,英文全称indexconditionpushdown,简称icp,用于优化数据查询,下面一起来看一下,希望对大家有帮助。推荐学...

  • 周排行
  • 月排行
  • 年排行

精彩推荐