Mysql 索引优化

前驱知识

1.Explain关键词Mysql优化之Explain

2.联合索引结构

现有 people 表数据如下:

people表

如下面 SQL 语句建立索引:

create index idx_lnameFnameDob on people(last_name, first_name, dob);

其索引结构为:

联合索引

对于表中的每一行数据,联合索引包含了 last_name,,first_name 和 dob 列的值。对于相同 last_name 的值,则根据 first_name 来排序,对于相同的 last_name 与 first_name,则根据 dob 来排序。

常见的索引优化方法

现有如下职工表:

staffs表

对 name,age,pos 建立联合索引:

ALTER TABLE staffs ADD INDEX index_staffs_nameAgePos(name,age,pos);

1.违背最左前缀法则

最左前缀法则:使用联合索引进行查询,查询应从索引的第一列开始,并且不跳过索引中的列。

  1. 针对name,name and age,name and age and pos查询:

1.1

通过 explain 我们不难看出,三个查询都使用了索引index_staffs_nameAgePos,但是 key_len 不同,ref 列中的 const 数量也不同,这是因为每次查询精度变高了使用到索引的地方变多,这只是个铺垫,重点在下方。

  1. 针对age and pos,pos,name and pos查询:

1.2

可以看到对 age and pos,pos 的查询没有使用索引,这是因为联合索引 index_staffs_nameAgePos 是根据 name 属性建立的,根据最左前缀法则,没有从对索引第一列 name 开始查询,因此无法使用该索引。

对 name and pos 的查询使用到了索引,但通过观察可以看出,ref 列只有一个 const,按照最左前缀法则,该查询跳过了中间列 age,因此对pos上的查询无法使用上该索引。

2.在索引上做任何操作(计算、函数、类型转换)

  1. 在索引上进行函数操作

2.0

使用LEFT(name, 4)获取 name 属性的左边四位字符,可以看出搜索结果没有错误,但是通过 explain 分析,不使用 left 的 SQL使用了索引,使用了 left 的 SQL 没有使用索引。

  1. 在索引上进行类型转换

2.1

name 属性是字符(varchar)类型,不加引号时,存储引擎认为2000时整数型,赋值给 name 会自动转换成字符型,正因为这个类型转换,导致索引失效。

3.范围查找右边的属性索引失效

3.0

key_length 表示索引中使用的字节数,可以看出第二个查询索引使用的更充分。这两个查询的唯一不同在于第一个查询对 age 进行范围查找,第二个查询对 pos 进行查找。而范围查找会导致右边的属性失效,因此第一个查询会导致联合索引对 pos (age 右边的属性)的检索失效。而 pos 右侧属性为空,因此不会导致索引失效。

结合联合索引的结构图,我们可以进一步分析:

第一个查询中肯定使用上了联合索引中的 name 属性,查找到所有的 July 叶子节点,再使用 age 属性,查找到所有满足范围查找条件的数据,根据联合索引建立的原理,对相同 age 值的pos 值进行排序,因此 age 范围查找之后的 pos 不满足有序性,因此联合索引对 pos 的检索失效。

4.尽量使用覆盖索引,减少 Select *

覆盖索引:Select 的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。

4.0

第二个查询的 Extra 列多了 Using Index,表示使用了覆盖索引。两句SQL的输出分别为:

4.1

第一句SQL多了add_time属性,由于索引中不包含 add_time 属性,因此 Mysql 根据联合索引找到这条数据的主键 id 时,需要返回主键索引再查找一次,这个过程也称为回表。回表会降低 Mysql 性能。所以在编写SQL语句时,尽量减少 Select * 的使用,减少回表的次数。

5.不等于( != 或 <>)无法使用索引

5.0

索引无法对不等于起作用,不等于会导致全表扫描。

6.判断是否为空( is null 或 is not null)无法使用索引

6.0

7.使用连接词OR会导致索引失效

7.0

Optimizer(查询优化器)很难优化连接词 or,可以使用 union 进行替代。只有在 or 无需索引,且数据量较小时可以考虑使用。

8.通配符开头的 LIKE 查询导致索引失效

  1. 通配符(%)放在字符串左边会导致索引失效

8.0

第一二句 SQL 无法使用索引,第三四句 SQL 使用了索引。可以看出通配符放在最左边无法使用,放在中间或右边可以使用索引。

MySQL 不能在索引中执行 LIKE 操作。这是底层存储引擎 API 的限制。但 MySQL 可以在索引中做最左前缀匹配的 LIKE 比较,因为该操作可以转换成简单的比较操作,但是如果是通配符开头的 LIKE 查询,存储引擎就无法做比较匹配。这种情况下,MySQL 服务器只能全表扫描。

  1. 通过覆盖索引实现优化

8.1

由于 Select 选中的列与 WHERE 过滤条件都可以被索引覆盖,因此优化器话选择通过索引查找。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值