SQL之索引优化

1 索引三大特性

索引的高度比较低:查询快,快速定位。sql

索引自己能存储列值:索引自己存储列值(索引值+rowid),用来优化count(*),sum(索引类)等函数。函数

索引自己有序:优化MAX/MIN,ORDER BY等排序。性能

注:建议表字段尽可能不为null。由于索引的时候字段为null会致使索引失败(不加索引字段 is not null排除的状况下。)测试

通常须要创建索引的字段优化

一、常常用在where语句以后的字段

二、主键或者外键

三、字段具备惟一性的时候创建惟一性索引

四、在常常须要根据范围进行搜索的列上建立索引,由于索引已经排序,其指定的范围是连续的

五、返回数据占总数的5%之内。

优势:查询优化后变快。code

缺点:建索引须要占空间,并且须要花时间维护。更新数据须要更新索引来保持索引有序。排序

2 单索引优化sql

测试数据1000000条。索引

表t7结构class

名称        类型             是否为空
ID          NUMBER          N
ID2         NUMBER          N
CONTENTS    VARCHAR2(1000)  N

2.1.索引存储值优化countselect

drop index idx1_t7_id2

 1.select count (*) from t7 --11.373s
 2.select count (*) from t7 where id2 is not null --11.662s
 3.select count (1) from t7 --11.186s
 4.select count (id2) from t7 --11.653

 create index idx1_t7_id2 on t7(id2)

 1.select count (*) from t7 --12.136s
 2.select count (*) from t7 where id2 is not null --0.473s
 3.select count (1) from t7 --11.778s
 4.select count (id2) from t7 --0.472s

观察能够看出,一、三、5对应sql执行时间基本没有变化。

可是二、4对应sql都从11秒左右提高到0.47s左右(第二次查询达到了0.063)。时间缩短了20多倍。明显索引列(id2)在sql语句中被使用到。

:count使用索引统计时优化时,sql中须要用到索引列,且该列值不能为空(若是为null,须要加is not null剔除列里面的空值),不然索引失效。若是索引列主键不为空,count(*)会用到索引。

2.2 索引存储列值sum与avg

drop index idx1_t7_id2

select sum (id2) from t7  --11.139s
select sum (id2) from t7  where id2 is not null--12.044s

create index idx1_t7_id2 on t7(id2)

select sum (id2) from t7  --1.375s
select sum (id2) from t7  where id2 is not null--1.326s (效果等价于索引列不为null)

sum (索引列)能够优化sum函数查询,前提是索引列不为null或者排除索引列的空值,avg效果同样。

2.3索引自己有序之order by

drop index idx1_t7_id2

1.select *  from t7 order by id2 --27.176s
2.select id2 from t7  order by id2 --12.356s
3.select id,id2 from t7 order by id2 --11.529s
4.select * from t7 where id2 >0 order by id2 --27.3s
5.select * from t7 where id2 >0 and id2<10000 order by id2 --12.012s
6.select * from t7 where id2=3 order by id2 --12.3s

create index idx1_t7_id2 on t7(id2)

1.select * from t7  order by id2  --25.586s
2.select id2 from t7  order by id2 --0.452s
3.select id,id2 from t7 order by id2 --11.435s
4.select * from t7 where id2 >0 and id2<10000 order by id2 --0.032s(id2必须字段最大与最小范围,此处只是缩小了搜索范围,不然无效)
5.select * from t7 where id2 =3 order by id2 --0.031s

观察会发现2,4,5对应sql执行时间变短。此时不是使用order by的排序,而是使用索引的排序。

1.返回字段只有索引字段,以索引字段进行排序。索引有效。
2.返回字段不止索引字段,以索引字段排序,此时索引字段必须在where中指定范围(做用是缩写范围,我的认为不是索引的效果)。

2.4索引有序优化max与min

drop index idx1_t7_id2 

1.select max(id2) from t7   --12.309s
2.select min(id2) from t7   --12.169s
3.select max(id2),min(id2) from t7   --12.465s
4.select a.max,b.min from (select max(id2) max from t7) a,(select min(id2) min from t7 ) b --22.573s

create index idx1_t7_id2 on t7(id2)

1.select max(id2) from t7 --0.608s
2.select min(id2) from t7   --0.436s
3.select max(id2),min(id2) from t7   --1.279s
4.select a.max,b.min from (select max(id2) max from t7) a,(select min(id2) min from t7 ) b --0.031

注:走索引时,4比3效果好。

3 组合索引优化sql

适用场景:单列查询结果多,组合查询结果少。(按索引建立顺序生效,中间索引断层(where条件中),左边索引字段生效,右边索引字段不生效)

1.须要考虑组合顺序;
2.只有等值查询是,组合索引顺序不影响性能;
3.通常将等值列放在索引前面。

组合索引sql案例

1.范围查询时,不要使用in,应该使用范围(>,<)

4 分区索引

若是表关联查询时分区条件没法使用到,此时全局索引性能会比分区索引效果好(索引高度缘由)。

5 索引的失效

5.1 逻辑失效

1.索引不能存储空值,不然索引失效。(用is not null索引字段会有效);

2.like会使索引失效,以%开头。(可是索引开头能肯定的时候like能够用到索引);

3.order by(除非order by 后字段出如今where条件中,或者只是返回order by后的索引字段才会索引生效);

4.对索引列进行运算将用不到索引,应该讲索引列放在比较运算符的左边(=,<,>等),运算逻辑放右边;

5.索引列发生类型转换;

6.条件中用or,即便其中有条件带索引,也不会使用索引查询;

7.对于多列索引,不是使用的第一部分,则不会使用索引;

8.组合索引的第一列没有出如今where条件中时。

5.2 物理失效

1.move操做,须要重建索引;

2.分区表致使。

总结

因为索引的创建会形成开销,且会使增删改须要维护索引顺序等缘由。创建索引时不该该出现无用或者大量重复交叉的索引。且组合索引列不该该超过4个。索引的选择应该建在数据量大,可是返回数据少的表。

参考

[1]粱敬彬,粱敬弘。 收获,不止SQL优化[J].电子工业出版社,2017.6