索引优化
1、 分析SQL执行的性能
使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理SQL语句的。分析所编写的查询语句或是表结构的性能瓶颈。
具体语法:
EXplain DQL语句;
执行的结果一共包括以下几个字段:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | roes | filtered | extra |
---|
字段 | 描述 |
---|---|
id | 查询的序列号,是一组数字,用来表示查询中执行select子句或者是操作表的顺序。 |
select_type | 表示查询的类型,一般有SIMPLE(简单查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION 中的第二个或者后面的查询语句)、SUBQUERY(子查询中的第一个 SELECT) |
table | 查询所用的表 |
partitions | 显示的为分区表命中的分区情况,非分区表该字段为空(null)。5.7以后就是默认项 |
type | 连接的类型 |
possible_keys | 可能使用的索引 |
key | 实际使用的索引 |
key_len | 索引字段的长度 |
rows | 扫描行的数量 |
extra | 执行情况的说明和描述 |
type连接类型性能由好到差的连接类型为( system —> const -----> eq_ref ------> ref-------> ref_or_null----> index_merge —> index_subquery -----> range -----> index ------>all )
EXTRA属性:
using index :使用覆盖索引时会出现。
using where:在查找使用索引的情况下,需要回表去查找所需的数据。
using index condition:查找使用了索引,但是需要回表查找数据。
using index ; using where:查找使用了索引,且需要的数据都在索引列中,不需要回表查询数据。
2、 防止索引失效
2-1 全值索引
对索引中所有的列都指明值,是做好用的一种避免索引失效的方法。
案例:查询1班身份证号为123456的学生的信息。
1.建立索引:
mysql> create index careId_class_index on admin(careId,class);
Query OK, 0 rows affected
Records: 0 Duplicates: 0 Warnings: 0
2.查看索引:
mysql> show index from admin;
+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| admin | 0 | PRIMARY | 1 | id | A | 5 | NULL | NULL | | BTREE | | |
| admin | 1 | careId_class_index | 1 | careId | A | 5 | NULL | NULL | | BTREE | | |
| admin | 1 | careId_class_index | 2 | class | A | 5 | NULL | NULL | | BTREE | | |
+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set
3.使用索引
3.1 不采用全值索引
mysql> explain select * from admin where careId = '123456';
+----+-------------+-------+------------+------+--------------------+--------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+--------------------+--------------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | admin | NULL | ref | careId_class_index | careId_class_index | 22 | const | 1 | 100 | NULL |
+----+-------------+-------+------------+------+--------------------+--------------------+---------+-------+------+----------+-------+
1 row in set
3.2 采用全值索引
mysql> explain select * from admin where class = '1' and careId = '123456';
+----+-------------+-------+------------+------+--------------------+--------------------+---------+-------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+--------------------+--------------------+---------+-------------+------+----------+-------+
| 1 | SIMPLE | admin | NULL | ref | careId_class_index | careId_class_index | 44 | const,const | 1 | 100 | NULL |
+----+-------------+-------+------------+------+--------------------+--------------------+---------+-------------+------+----------+-------+
2-2 最左前缀法则
定义: 如果在索引中包含了多个字段,即采用复合索引时,通常需要遵循最左前缀原则,即查询从索引的最左前列开始,并且不跳过索引中的列。
案例:
1 .索引不是失效
1.创建索引
mysql> create index careId_class_index on admin(careId,class);
2.使用索引
mysql> explain select * from admin where careId = '123456';
mysql> explain select * from admin where careId = '123456' and class = '1';
2.索引失效:没有遵循最左前缀原则,跳过第一个索引的字段。
1.创建索引
mysql> create index careId_class_index on admin(careId,class);
2.使用索引
mysql> explain select * from admin where class = '1';
3.如果出现遵循了最左前缀原则,但是后面跳跃了一个字段,则跳跃后的字段索引失效,此时只有最左端的字段的索引起作用。
2-3 比较后失效
在使用范围查找时,后面的索引失效,简言之就是使用比较运算符后的查找条件的索引失效。
案例:
1.创建索引
mysql> create index index_careId_class_age on admin(careId,class,age);
2.使用索引
可知:前面两个字段careId、class使用了索引,但是age没有使用索引,即比较后索引失效。
2-4 索引列运算失效
在索引包含的列上进行各种运算,会导致进行全表扫描,此时索引失效。
案例:
1.创建索引
mysql> create index name_index on admin(name);
Query OK, 0 rows affected
Records: 0 Duplicates: 0 Warnings: 0
2.使用索引
mysql> explain select * from admin where substring(name,2,1)='o';
结果:此时进行全表扫描
2-5 字符创不加单引号
一般情况下如果一个字符创不加单引号,此时索引会失效,因为对字符串加单引号,MySQL的查询优化器,会自动的进行类型转换,造成索引失效。
案例:
1.加单引号,没有失效
mysql> explain select * from admin where careId = '123456' and class = '1';
2. 没加单引号,此时没加单引号的索引失效,
mysql> explain select * from admin where careId = '123456' and class = 1;
2-6 尽量不使用全部查询
即尽量别使用像select * 这样的语句,多使用覆盖查询,也就是索引的字段。如果查询的列多出了建立索引时所用的列,此时也会影响查询的效率。
案例:
1.select *
mysql> explain select * from admin where careId = '123456' and class = '1' and age =18;
2.超过索引的范围
mysql> explain select name,age from admin where careId = '123456' and class = '1';
2-7 在条件查询中使用或者(or)关键字时,索引失效。
在使用or进行条件筛选时会使索引失效。
mysql> explain select * from admin where careId = '123456' or class = '1';
此时可以使用合并查询union来代替
mysql> explain select * from admin where careId = '123456' union all select * from admin where class = '1';
2-8 在模糊查询like中,分情况
通配符%在前失效,但是在尾部时索引不会失效,即前失后保。
1.通配符在最前端。
mysql> explain select * from admin where name like'%o';
2.通配符在后端。
mysql> explain select * from admin where name like'j%';
2-9 判空不一定
判空主要有两个操作运算符:is null 与 is not null,使用判空运算符时主要看数据表在设计时是否可以为空,从而来判断索引是否失效。
2-10 不等号不一定
在使用不等于运算符(!= <>)时可能索引会失效。
mysql> explain select * from admin where careId <> '123456';
mysql> explain select * from admin where admin.careId = '123456';
2-11 多使用复合索引
当多个字段需要建立索引时此时就可以使用复合索引,即建立一个索引相当于建立了好几个索引。
创建复合索引:
mysql> create index deptno_sal_index on emp(deptno,sal);
相当于建立了两个索引:
deptno
deptno + sal
创建单列索引:
mysql> create index deptno_index on emp(deptno);
mysql> create index sal_index on emp(sal);
在使用索引时,数据库会选择一个最优的索引(辨识度最高索引)来使用,并不会使用全部索引 。
--------------------------------------END------------------------------------
数据库索引基础:----------------------------------------------------《加载完成》------------------------------------------------------------------------------