前言
这几天抽了个时间将《高性能Mysql》看了一下忽觉索引非常之重要,习之然后总结巩固知识。本文索引使用的是InnoDB存储引擎。因为本文并不是说用索引的好处,所以并不会书写QPS之类的测试结果请大家见谅。我的mysql版本是8.0.11。
目录
(一)索引使用优化
①独立的列
②覆盖索引
③索引匹配
(二)索引创建优化
①前缀索引和索引选择性
②选择合适的索引顺序
③不创建冗余和重复索引
索引使用优化
我们有时候虽然创建了合适的索引但是使用不当依然会使索引失效,所以我将书上的索引使用大致总结了一下。在这之前我先介绍一下EXPLAIN生成结果中字段type和Extra的意义,先说一下type常出现的结果。
(1)const 表中最多只有一行用于主键和唯一索引的匹配
(2)all全表扫描
(3)ref使用索引并符合最左匹配
(4)index :❶
a.当查询是索引覆盖的,即所有数据均可从索引树获取的时候(Extra中有Using Index);
b.以索引顺序从索引中查找数据行的全表扫描(无 Using Index);
c.如果Extra中Using Index与Using Where同时出现的话,则是利用索引查找键值的意思;
d.如单独出现,则是用读索引来代替读行,但不用于查找
接下来我们解释一下Extra出现的结果:
(1)using index 使用覆盖索引。
(2)using where 条件语句中部分条件使用的是索引,其他条件需要去表中筛选。
(3)using inex condition 条件语句中所有条件都在索引中,但是所需要的数据不在索引中。
(4)using where;using index 条件和所需数据都在索引中。
独立的列
独立的列一眼上看去以为是针对于一个单独的列创建索引但是实际上并不是这样的。“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数❷。这句话的前面一句话在书上是:如果使用独立的列则mysql不会使用索引。这句话有点模棱两可,“不会使用索引”到底是包括索引全扫描还是不包括索引全扫描,如果包括的话则与实验结果不相符,如果不包括的话那就没问题了。废话不多说还是用结果来证明吧。首先我的数据库表结构是这样子的,如下图所示:

我创建了两个单独列的索引用来测试表达式和函数如下图所示:


测试sql: explain select age from user where age =2;

从测试结果中我们可以看到type为ref(使用BTree索引),Extra为Using index(使用了覆盖索引)
如果我们把sql语句改为: explain select age from user where age+1=2;解释结果如下所示:

可以看到这条查询语句是使用了索引的,不过是扫描索引的全部数据。接下来测试一下如果条件语句中使用了函数是否会使用索引我的sql语是:EXPLAIN SELECT id from user where TO_DAYS(birthday) >= 50000000;测试结果如下图所示:

OK,结果也是index。至于书上那句话是对是错我就不得而知了,不过大家可以自己去测试一下。
覆盖索引
如果把使用索引比作你开了一辆五菱宏光的话,那么你使用覆盖索引就是开了一辆兰博基尼(兰博基尼的性能是由你自己来决定的)。覆盖索引简单的来讲就是你所要查询的字段和条件语句都在一条索引中。接下来又是证明的过程,我创建一个新的索引如下图所示:

然后我使用这条sql语句 EXPLAIN SELECT first_name,age from user where first_name='张' and age >0,在这条sql语句中我查询两个不同索引中的列查询结果如下所示;

在这条sql语句中我使用了两个索引idx_fk_name和idx_fk_age,查询的列和查询条件都是在这两个索引中,测试的结果为using where(需要回表查询所需要的数据)。接下来我们使用这个sql语句 EXPLAIN SELECT last_name FROM user where first_name = '张',使用结果如下图所示:

索引匹配
如果我们书写的sql语句符合索引匹配原则,那么我们就可以不进行索引的全部数据扫描,结果就是我们的查询效率又变高了。那么索引匹配原则是啥?我就简略的总结一下吧。
全值匹配
全值匹配就是查询条件和索引中的所有列进行匹配。如我上面创建的idx_fx_name索引。select * from user where first_name='张' 和 last_name = '三' 这条sql语句就是全值匹配。注意如果写成last_name='三' and first_name='张'也是全值匹配
最左匹配
我把书中匹配最左前缀和匹配列前缀都划分为最左匹配,因为我觉得它都是从最左边开始匹配的,好像网上也是这么说的。
最左前缀就是你写的条件查询语句针对于某个索引来说它符合从左边一个一个进行匹配的方式(经过实测条件语句的顺序不影响最左匹配的原则),再拿我的idx_fx_name索引来举个例子。如select * from user where last_name = '三'和 select * from user where first_name = '张' 这两个sql语句查询索引的方式都不一样,前者是扫描索引所有数据,第二个就只扫描了索引的部分数据。测试结果如下所示:


匹配范围值
在符合最左匹配的基础上可以使用范围进行查询。
精确匹配加范围匹配
在符合最左匹配的基础上最后一个查询条件可以记性范围查询。
索引创建优化
前缀索引和索引选择性
我们先说说索引的选择性吧。索引的选择性是指不重复的索引值(也称为基数,cardinal
