摘要:随着数据库的数据量逐渐增大,查询数据的性能会越来越差。此时需要针对查询频繁的表建立索引,索引是一种高效获取数据的数据结构,但是索引也不是越多越好,索引越多,维护索引结构的代码就越大,会影响增删改查的效率。因此,本文主要研究索引在几种场景下的正确使用,并通过几种性能分析的方式,分析其查询性能,结果说明,使用正确使用索引的情况下,查询性能有大幅度的提高。

1、索引的概念与分类

2、索引的结构及原理

3、索引的性能分析

4、索引的设计原则及使用场景

设计原则1:针对数据量较大,且查询比较频繁的表才建立索引。

设计原则2:针对常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引

  • 使用场景1:查询字段为单列字段(针对1000w数据的表tb_bigdata)
select name from tb_bigdata where name='张先生1';

不使用索引:5.462秒

多个索引 查找 索引越多查询越快_mysql

根据name建立普通索引

create index idx_name on tb_bigdata(name);

数据量大时建立索引的时间也比较长:24秒

多个索引 查找 索引越多查询越快_mysql_02

使用索引下的查询结果:

多个索引 查找 索引越多查询越快_字段_03

设计原则3:尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。

查询索引:

show index from tb_bigdata;

多个索引 查找 索引越多查询越快_mysql_04

id是tb_bigdata表的主键索引,建表时默认建立主键索引,可见主键索引的效率比普通索引的高。

多个索引 查找 索引越多查询越快_sql_05

  • 使用场景2:查询字段为多列字段

首先删除刚才建立的单列索引:

drop index idx_name on tb_bigdata;

查看场景2的查询性能:

select * from tb_bigdata where birth =1981 and name='张先生71';

不使用索引:

多个索引 查找 索引越多查询越快_sql_06

设计原则4:如果存在多个查询条件,尽量使用联合索引,减少单列索引,因为联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。

覆盖索引:查询使用了索引,并且需要返回的列,在该索引中全部都能找到。尽量使用覆盖索引,减少select *。

上面sql优化成:

select id,birth,name from tb_bigdata where birth =1981 and name='张先生71';

单列索引与联合索引对比:

  • 对于多个查询字段的索引(name,birth),如果只有单列索引,那么mysql最终也只能走其中一个,此时是需要回表查询的。

多个索引 查找 索引越多查询越快_字段_07


使用单列索引:idx_name

多个索引 查找 索引越多查询越快_字段_08


结果:8ms

多个索引 查找 索引越多查询越快_mysql_09

  • 如果查询使用的是联合索引,具体的结构如下,再加上使用覆盖索引,避免回表查询。
    使用联合索引:idx_birth_name:
create index idx_birth_name on tb_bigdata(birth,name);

多个索引 查找 索引越多查询越快_数据库_10


多个索引 查找 索引越多查询越快_字段_11

设计原则5:最左前缀法则:如果使用了联合索引,查询sql中的条件必须存在索引最左边的列(顺序无关),否则索引全部失效;而且中间不能跳过索引中的某一列,否则该列后面的字段将失效。

对于索引:idx_birth_name_sex;

explain select * from tb_bigdata where birth =1981 and name='张先生71' and sex='男';

多个索引 查找 索引越多查询越快_sql_12

explain select * from tb_bigdata where birth =1981 and name='张先生71';

多个索引 查找 索引越多查询越快_mysql_13

explain select * from tb_bigdata where birth =1981;

多个索引 查找 索引越多查询越快_字段_14


这三组结果说明,由于查询sql中都包含索引的第一列(birth),因此索引都会生效,但是索引长度不同,可推断出birth索引长度为5,name索引长度为152,sex索引长度为152。

explain select * from tb_bigdata where name='张先生71' and sex='男';

查询条件不包含索引最左列,索引失效

多个索引 查找 索引越多查询越快_mysql_15


查询条件中包含索引最左列,但是中间跳过了索引的某一列(name),从索引长度可看出name以及后面索引字段将失效。

explain select * from tb_bigdata where birth =1981 and sex='男';

多个索引 查找 索引越多查询越快_数据库_16


联合索引的原理:

多个索引 查找 索引越多查询越快_多个索引 查找_17

5、索引失效场景