一、索引的使用场景

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应用ArkUI 状态管理开发范例

      本文转载自<#2023盲盒+码# OpenHarmony应用ArkUI 状态管理开发范例>,作者:zhushangyuan_ 本文根据橘子购物应用,实现ArkUI中的状态管理. 在声明 ...

  2. Docker学习路线13:部署容器

    部署容器是使用Docker和容器化管理应用程序更高效.易于扩展和确保跨环境一致性性能的关键步骤.本主题将为您概述如何部署Docker容器以创建和运行应用程序. 概述 Docker容器是轻量级.可移植且 ...

  3. Go 语言输出文本函数详解

    Go语言拥有三个用于输出文本的函数: Print() Println() Printf() Print() 函数以其默认格式打印其参数. 示例 打印 i 和 j 的值: package main im ...

  4. Python设计模式----3.单例模式

    单例模式:主要目的是确保某一个类只有一个实例存在 代码: class A(): def __new__(self, *args, **kwargs): if not hasattr(self, 'na ...

  5. 机器学习&深度学习 操作tips

    1. 在运行程序时,报错如下: usage: run.py [-h] --model MODEL [--embedding EMBEDDING] [--word WORD] run.py: error ...

  6. 重新点亮shell————语法[四]

    前言 简单介绍一下语法. 正文 数组: 定义数组: IPTS =(10.0.0.1 10.0.0.2 10.0.0.3) 显示所以数组元素: echo ${IPTS[@]} 显示数组元素的个数 ech ...

  7. jenkins 持续集成和交付——maven小栗子(四)

    前言 因为前面一节中介绍了自由风格模式,这里介绍一个专门为maven打造的模式,没错就是使用插件.这里写这个只是为了说明,如果我们构建一些不是那么复杂的项目,那么可以去使用一些插件,这样可以更加方便, ...

  8. pytorch,numpy两种方法实现nms类间+类内

    类间:也就是不同类之间也进行nms 类内:就是只把同类的bboxes进行nms numpy实现 nms类间+类内: import numpy as np # 类间nms def nms(bboxes, ...

  9. leetcode第 181 场周赛

    5364. 按既定顺序创建目标数组 给你两个整数数组 nums 和 index.你需要按照以下规则创建目标数组: 目标数组 target 最初为空. 按从左到右的顺序依次读取 nums[i] 和 in ...

  10. sass的用法重温

    Sass使用变量,变量以$开头 $bgcolor:#f40; background-color:$bgcolor; 如果变量需要嵌套在字符串当中,就需要写在#{}之中 $direction:left; ...