mysql 查询使用索引

前面文章介绍了InnoDB的索引结构是B+树。主键索引树上拥有所有行数据记录,使用索引可以提高数据库查询的性能和效率,加快数数据查询速度。

索引覆盖

要查询的字段都在索引树上,一次索引树查找就可以完成查询。聚簇索引也就是主键索引满足索引覆盖。

回表

针对辅助索引,要查询获取非索引列的值,需要根据索引列对应的主键再从聚簇索引查询获取一次,这叫做回表。

如:select * from web_user where username like '曹%';假设username 上有索引,但是是select *是查询所有字段,username上的索引不满足检索要求,需要根据username上索引获取主键后再依次去主键索引上去加载数据。增加了IO操作。相反如果select id,username则只在username索引上一次查找就可完成。

为了避免回表,查询应尽量查询必要字段,避免select *。可以在合适的字段创建复合索引。

最左匹配原则

因为InnoDB在构建索引时候是按索引key值顺序从第一个然后依次往右进行排序的,所以在索引匹配的时候要从最左边key进行匹配。也就是查询条件要包含最左侧值。

如user表有(name,age,city)联合索引,

以下会使用索引

复制代码
where name='xxx' and age>20;
where name like 'xx%';

以下不会使用索引

复制代码
where age>20;
where name like '%xx%';
where age>20 and city='xx';

部分使用

复制代码
where name='aa' and city='xx';//city不会使用
where name='aa' and age>20 and city='xx';//city不会使用,被age的范围查找打断

使用到索引一般在执行计划分析Extra会有Using index condition信息。

在mysql8中对联合索引也做了一些优化,对应违背最左匹配原则的条件,可能的情况下使用索引跳跃扫描(Index Skip Scan)。比如where age=20可能会跳过name,然后使用age对应的key进行匹配,原理是拿出name对应的所有值与age条件进行组合,由此可见只有name的可能值足够少时才划算。一般在Extra列里显示Using index for skip scan表示使用了索引跳跃扫描。索引跳跃扫描有很多限制条件,执行计划要考虑很多情况判断是否走索引跳跃扫描。

要使用索引跳跃扫描要在optimizer_switch设置skip_scan=on。

索引失效

在以下几种情况下,索引会失效

1、在索引字段上使用函数

2、like以 %开头

3、使用or连接多个条件,如果有一个条件没有索引则整个or连接两侧条件都无法使用索引。

4、数据类型不匹配,隐式类型转换。如where name=123。

5、null或is not null判断不走索引。因为索引树上没有null值。

6、不等于操作不会走索引。

这几种场景如果理解了B+树结构,想一想就能够理解为什么索引会失效,这里不做过多的赘述。在where条件中尽量避免这些情况的发生。

可以回看下文章 Mysql B+树索引

索引下推(Index Condition Pushdown (ICP))

索引下推是MySQL中的一种优化技术,用于在使用索引检索表中的行时提高性能。当没有启用ICP时,存储引擎会遍历索引以定位基表中的行,并将它们返回给MySQL server层,然后MySQL server对这些行进行WHERE条件的评估。启用ICP,如果WHERE条件的部分可以通过仅使用索引中的列来评估,MySQL服务器将这部分WHERE条件下推给存储引擎。存储引擎通过使用索引条目来评估下推的索引条件,只有在条件满足时才从表中读取行。ICP可以减少存储引擎访问基表的次数,以及MySQL server访问存储引擎的次数。

一般情况下在执行计划Extra列显示Using index condition表示使用了索引下推。

举个例子

表people有以下联合索引(zipcode, lastname, firstname)

复制代码
SELECT * FROM people
  WHERE zipcode='95054'
  AND lastname LIKE '%etrunia%'
  AND address LIKE '%Main Street%';

首先zipcode='95054'列可以使用索引,lastname LIKE '%etrunia%'虽然是索引列但是不满足索引条件。如果没有索引下推,会返回所有满足zipcode='95054'条件的列。在有索引下推的情况下,因为lastname是索引的一部分,在扫描整行数据前,会检查lastname对应的索引部分,是否满足LIKE '%etrunia%'条件。不会返回满足zipcode条件而不满足lastname的行。

可以通过optimizer_switch参数来开启索引下推。

复制代码
SET optimizer_switch = 'index_condition_pushdown=on';

索引下推适用于 range, ref, eq_ref, and ref_or_null 普通索引,常见于复合索引。因为主键索引是唯一,不需要再评估其它条件,没有索引下推情况。

相关推荐
2501_941805933 小时前
在大阪智能零售场景中构建支付实时处理与高并发顾客行为分析平台的工程设计实践经验分享
数据库
李慕婉学姐3 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
珠海西格电力3 小时前
零碳园区有哪些政策支持?
大数据·数据库·人工智能·物联网·能源
哈里谢顿4 小时前
记录一次sql优化记录
mysql
数据大魔方4 小时前
【期货量化实战】日内动量策略:顺势而为的短线交易法(Python源码)
开发语言·数据库·python·mysql·算法·github·程序员创富
Chasing Aurora4 小时前
数据库连接+查询优化
数据库·sql·mysql·prompt·约束
倔强的石头_4 小时前
【金仓数据库】ksql 指南(六)—— 创建与管理用户和权限(KingbaseES 安全控制核心)
数据库
小熊officer5 小时前
Python字符串
开发语言·数据库·python
渐暖°5 小时前
JDBC直连ORACLE进行查询
数据库·oracle
萧曵 丶6 小时前
Next-Key Lock、记录锁、间隙锁浅谈
数据库·sql·mysql·mvcc·可重复读·幻读