一、索引的使用场景

1、全值匹配

通过主键索引查询

mysql> explain select * from t_goods where id = 1 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

可以看到这里查询数据使用了主键索引。

现在我们再创建一个索引。

ALTER Table t_goods ADD INDEX index_category_name(t_category_id,t_name);

这里为t_category_id与t_name创建了联合索引。

mysql> explain select * from t_goods where t_category_id = 1 and t_name = '手机' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ref
possible_keys: index_category_name
key: index_category_name
key_len: 208
ref: const,const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

这里的查询条件为t_category_id与t_name,所以查询时使用了联合索引index_category_name

2、查询范围

对索引的值进行范围查找

mysql> explain select * from t_goods where id >= 1 and id <=20 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 15
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

type: range说明根据主键索引范围进行查询。这里 Extra: Using where,说明MySQL按照主键确定范围后再回表查询数据。

3、匹配最左前缀

解释:也就是说,在使用索引时,MySQL优化器会根据查询条件使用该索引。只有满足这个匹配原则才会使用索引。例如过程创建的联合索引index_category_name(t_category_id, t_name),如果我跳过t_category_id直接使用t_name条件查询,那么这个查询将不会使用索引。

mysql> explain select * from t_goods where t_name='手机' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 10.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

可以看到这个查询并没有使用索引。

4、查询索引列

如果在查询时包含索引的列或者查询的列都在索引中,那么查询的效率会比SELECT * 或者查询没有索引的列的效率要高很多。也就是说,如果查询的列只包含索引列,那么这个效率会高很多。例如

mysql> explain select t_name,t_category_id from t_goods where t_name='手机' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: index
possible_keys: index_category_name
key: index_category_name
key_len: 208
ref: NULL
rows: 15
filtered: 10.00
Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)

例如这里查询的列都是索引列,所以这个查询的效率会快很多,并且使用了索引。如果有其他不是索引列需要查询,那么这个查询将不会使用索引。例如

mysql> explain select t_name,t_category_id,t_price from t_goods where t_name='手机' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 10.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

5、匹配字段前缀

如果某个字段存储的数据特别长的话,那么在这个字段上建立索引会增加MySQL维护索引的负担。匹配字段前缀就是用于解决这个问题。在字段的开头部分添加索引,按照这个索引进行数据查询。

例如在字段的前10个字符上添加索引,查询时进行匹配。

mysql> create index category_part on t_goods(t_category(10));
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

再次进行模糊匹配查询

mysql> explain select * from t_goods where t_category like '电子%' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: range
possible_keys: category_part
key: category_part
key_len: 43
ref: NULL
rows: 5
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

可以看到这里使用了我们刚才创建的索引,这个索引应用于字段的前10个字符。

6、精准与范围匹配查询

在查询数据时,可以同时使用两个索引,一个为精准匹配索引,一个为范围匹配索引。例如

mysql> explain select * from t_goods where t_category_id=1 and id>=1 and id<=10 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ref
possible_keys: PRIMARY,index_category_name
key: index_category_name
key_len: 5
ref: const
rows: 5
filtered: 66.67
Extra: Using index condition
1 row in set, 1 warning (0.00 sec)

这个查询使用了两个索引进行查找,使用index_category_name进行精准匹配并且按照主键索引进行范围查询

7、匹配NULL值

在查询一个字段时,如果这个字段是索引字段,那么在判断这个字段是否为空时也会使用索引进行查询。例

mysql> explain select * from t_goods where t_category_id is null \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ref
possible_keys: index_category_name
key: index_category_name
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: Using index condition
1 row in set, 1 warning (0.00 sec)

这里我查询t_goods表中t_category_idNULL的字段,可以看到这里是使用了索引进行查找的。

8、连接查询匹配索引

在使用JOIN连接语句查询多个数据表中的数据时,如果连接的字段上添加了索引,那么MySQL会使用索引查询数据

mysql> explain select goods.t_name,category.t_category from t_goods goods join t_goods_category category on goods.t_category_id = category.id \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: category
partitions: NULL
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 5
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: goods
partitions: NULL
type: ref
possible_keys: index_category_name
key: index_category_name
key_len: 5
ref: demo.category.id
rows: 5
filtered: 100.00
Extra: Using index
2 rows in set, 1 warning (0.00 sec)

在使用JOIN联合多表查询时,如果联合的字段是索引字段,那么这个查询也会使用索引列。

二、不适合使用索引的场景

1、以通配符开始的LIKE语句

在使用LIKE语句时,如果使用通配符%开头,那么MySQL将不会使用索引。例如

mysql> explain select * from t_goods where t_category like '%电' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 11.11
Extra: Using where
1 row in set, 1 warning (0.00 sec)

这里的t_category字段虽然说是索引字段,但是这里的条件是以通配符%开头,所以不会使用索引查询

2、数据类型转换

当查询的字段数据进行了数据转换时,也就是说,某个索引字段的类型为字符,但是在匹配条件时,不是字符类型,那么这个查询将不会使用索引查询。例如

mysql> explain select * from t_goods where t_category = 0 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: category_part
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 10.00
Extra: Using where
1 row in set, 3 warnings (0.00 sec)

例如这里的查询就没有使用索引,并且type的类型为ALL,说明进行了全表扫描查询。

3、OR语句

在OR语句中如果条件中有不是索引的字段,那么这查询就不会使用索引查询。例如

mysql> explain select * from t_goods where t_category_id = 1 or t_stock = 2 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: index_category_name
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 40.00
Extra: Using where
1 row in set, 1 warning (0.01 sec)

这里因为t_stock不是索引字段,所以哪怕t_category_id索引字段匹配成功,这条语句也不会使用索引查询

4、计算索引列

如果在使用索引条件时,这个索引字段进行了计算或者使用了函数,那么此时MySQL是不会使用索引的。

mysql> explain select * from t_goods where left(t_category,2)='电子'\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

这里对索引字段t_category使用了函数,判断这个字段的前两个字符是否为“电子”。可以看到有15条记录,但是并没有使用索引,哪怕t_category是索引列。

5、使用<>或!=操作符匹配查询条件

这两个符号都用于表示不等于。当查询条件使用这个时不会使用索引查询。

mysql> explain select * from t_goods where t_category<>'电子产品' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: category_part
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

6、匹配NOT NULL值

在MySQL中,使用IS NULL来判断索引字段会使用索引查询,但是使用NOT NULL来判断时不会使用索引查询。


mysql> explain select * from t_goods where t_category_id is not null \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: index_category_name
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

三、索引提示

1、使用索引

提示MySQL查询优化器使用特定的索引,不需要评估是否使用其他索引。

mysql> explain select * from t_goods use index(index_category_name,category_part) where (t_category_id = 1 and t_name='手机' ) or t_category = '电子产品'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: index_merge
possible_keys: index_category_name,category_part
key: index_category_name,category_part
key_len: 208,43
ref: NULL
rows: 6
filtered: 100.00
Extra: Using sort_union(index_category_name,category_part); Using where
1 row in set, 1 warning (0.00 sec)

这里可以使用use index()指定查询时使用特定的索引。但是MySQL仍然可以根据自身的优化器决定是否使用该索引。

2、忽略索引

可以在查询时,指定不使用某个索引。

mysql> explain select * from t_goods ignore index(category_part) where t_category = '电子产品'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15
filtered: 33.33
Extra: Using where
1 row in set, 1 warning (0.00 sec)

这里使用ignore index(),指定在查询时,忽略指定的索引,使用这条查询没有使用索引,而是进行全表扫描

3、强制使用索引

在查询数据时,强制使用某个索引来检索数据。

use index()的区别为,FORCE INDEX会强制使用指定的索引,而不会管MySQL的优化器如何选择。

mysql> explain select * from t_goods force index(category_part) where t_category = '电子产品'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t_goods
partitions: NULL
type: ref
possible_keys: category_part
key: category_part
key_len: 43
ref: const
rows: 5
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

MySQL的索引优化的更多相关文章

  1. 知识点:Mysql 数据库索引优化实战(4)

    知识点:Mysql 索引原理完全手册(1) 知识点:Mysql 索引原理完全手册(2) 知识点:Mysql 索引优化实战(3) 知识点:Mysql 数据库索引优化实战(4) 一:插入订单 业务逻辑:插 ...

  2. mysql使用索引优化查询效率

    索引的概念 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度.在没 ...

  3. mysql数据库索引优化与实践(一)

    前言 mysql数据库是现在应用最广泛的数据库系统.与数据库打交道是每个Java程序员日常工作之一,索引优化是必备的技能之一. 为什么要了解索引 真实案例 案例一:大学有段时间学习爬虫,爬取了知乎30 ...

  4. 【mysql】索引优化记录

    基础知识 Innodb存储引擎 支持行锁 支持事务: Myisam存储引擎 只支持表锁: 不支持事务: 常见索引列表 独立的列 前缀索引(索引选择性) 多列索引(并不是多个单列索引,索引顺序很重要) ...

  5. MySQL高级-索引优化

    索引失效 1. 2.最佳左前缀法则 4. 8. 使用覆盖索引解决这个问题. 二.索引优化 1.ORDER BY 子句,尽量使用Index方式排序,避免使用FileSort方式排序 MySQL支持两种方 ...

  6. MySQL的索引优化,查询优化

    MySQL逻辑架构 如果能在头脑中构建一幅MySQL各组件之间如何协同工作的架构图,有助于深入理解MySQL服务器.下图展示了MySQL的逻辑架构图. MySQL逻辑架构,来自:高性能MySQL My ...

  7. mysql数据库索引优化

    参考 :http://www.cnblogs.com/yangmei123/archive/2016/04/10/5375723.html MySQL数据库的优化:    数据库优化的目的:     ...

  8. MySQL的索引优化分析(一)

    一.SQL分析 性能下降.SQL慢.执行时间长.等待时间长 查询语句写的差 索引失效关联查询太多join(设计缺陷) 单值索引:在user表中给name属性创建索引,create index idx_ ...

  9. MySQL的索引优化分析(二)

    一.索引优化 1,单表索引优化 建表 CREATE TABLE IF NOT EXISTS article( id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO ...

  10. MySql数据库索引优化注意事项

    设计好MySql的索引可以让你的数据库飞起来,大大的提高数据库效率.设计MySql索引的时候有一下几点注意: 1,创建索引 对于查询占主要的应用来说,索引显得尤为重要.很多时候性能问题很简单的就是因为 ...

随机推荐

  1. OpenHarmony父子组件单项同步使用:@Prop装饰器

      @Prop装饰的变量可以和父组件建立单向的同步关系.@Prop装饰的变量是可变的,但是变化不会同步回其父组件. 说明: 从API version 9开始,该装饰器支持在ArkTS卡片中使用. 概述 ...

  2. 深入学习 XML 解析器及 DOM 操作技术

    所有主要的浏览器都内置了一个XML解析器,用于访问和操作XML XML 解析器 在访问XML文档之前,必须将其加载到XML DOM对象中 所有现代浏览器都有一个内置的XML解析器,可以将文本转换为XM ...

  3. Git 11 设置项目提交人

    前面介绍了可以给 Git 设置全局提交人,这样当前电脑所有项目提交人都会变成设置的值. 但实际开发中有时候需要给不同项目设置不同提交人. 比如工作的项目是一个提交人,自己维护的开源项目又是另一个提交人 ...

  4. java excel关联导入数据格式为一对多

    java excel关联导入数据格式为一对多 java 表格读取时一行一行的读取 将每行数据放入list  根据 list.stream().filter(m->m.getCode().equa ...

  5. 模拟spring工作原理

    1.配置文件 Service=service.Impl.ServiceImpl saveDao=dao.daoImpl.saveDaoImpl 2.模拟业务层 --接口 Service package ...

  6. 开源数据库OpenGauss的SQL解析源码分析

    开源数据库 OpenGauss 的 SQL 解析源码分析 OpenGauss 数据库体系概述 openGauss 是关系型数据库,采用客户端/服务器,单进程多线程架构:支持单机和一主多备部署方式,同时 ...

  7. 【7】SpringBoot是什么?SpringBoot的优缺点有哪些?

    随着动态语言的流行(Ruby.Groovy.Scala.Node.js),Java 的开发显得格外的笨重,繁多的配置.低下的开发效率.复杂的部署流程以及第三方技术集成难度大. 在上述环境下,Sprin ...

  8. Typora图床配置(Typora+PicGo+Github)

    Typora图床配置(Typora+PicGo+Github) 一.Github配置 登录github:https://github.com/ 新建仓库 生成私人令牌 Settings->Dev ...

  9. Flink Standalone集群jobmanagers高可用配置

    上篇文章简单叙述了Flink standalone集群的基础部署,在生产环境中假如只有1个jobmanager的话,那么这个节点一旦挂掉,所有运行的task都会中断,带来的影响比较大,因此在生产环境至 ...

  10. mysql8在Win10下安装教程

    一.准备工作 下载mysql8安装包,下载URL地址:https://mirrors.tuna.tsinghua.edu.cn/mysql/downloads/MySQL-8.0/ 二.管理员权限执行 ...