Mysql-高性能索引策略及不走索引的例子总结

Mysql-高性能索引策略

正确的创建和使用索引是实现高性能查询的基础。我总结了以下几点索引选择的策略和索引的注意事项:

索引的使用策略:

 (PS:索引的选择性是指:不重复的索引值,和数据表的记录总数(#T)的比值 ,范围从1/#T 到1之间,索引的选择性越高则查询效率越高,因为选择性搞得索引可以让Mysql在查找时可以过滤更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是更好

 计算列的选择性例子: mysql> select count(distinct city)/ count(*) from city_demo    )

1.为很长的字符列建立索引,应使用前缀索引(或者使用哈希索引多维护一个hash列),前缀索引是一种能使索引更小,更快的有效办法。选择前缀的长度要保证有较高的选择性。

(原因:索引过长的字符列,会让索引变的大而且慢。)

缺陷:Mysql无法使用前缀索引和哈希索引做order by 和 group by,也无法使用前缀索引和哈希索引做覆盖扫描。

2.选择合适的索引列顺序构建复合索引(需要考虑WHERE 条件,排序和分组等情况。当不需要考虑排序和分组时,将选择性更高的列放在前面通常时比较好的,同时也需要结合WHERE  查询条件中列 的出现频率的高低来调整索引列的顺序)

3.尽量使用索引扫描来做排序

(注意事项:只有当索引的列顺序和order by 子句 顺序完全一致,并且所有列的排序方向(倒序或正序)Mysql才能使用索引排序。如果查询需要关联多张表,则只有当 order by 子句的字段全部为第一个表时,才能使用索引做排序。 order by 子句使用索引排序也需要遵循最左前缀原则。

EXPLAN 分析执行语句,如果type列的值为“index”,则说明mysql 使用了索引扫描来做排序)

4.大多数情况不需要冗余索引,应该尽量扩展已有的索引而不是创建新索引。但也有时候出于性能方面的考虑需要冗余索引。因为扩展已有的索引会导致其变得太大,从而影响其他使用该索引的查询性能。

5.查询考虑覆盖索引,覆盖索引不需要回表查询,效率更高。

(注意事项:虽然覆盖查询效率更好,但也不能一味的为了覆盖查询把所有查询返回的列都加上索引,索引越多,mysql插入速度越慢)

总结:

总的来说,编写查询语句应该尽可能选择合适的索引来避免单行查找,尽可能地使用数据的原生顺序从而避免额外的排序操作,并尽可能的使用索引覆盖查询。

 

一些索引不生效的例子总结:

假如有如下数据表  create table user (

                                               name varchar(30)  not null,

             birthday date   not null,

                     address varchar(100) not null,

                                              age int(5) not null,

                                              card varchar(18)  not null,

                                              createtime date  not null,

               key(name,birthday,adress),

                                              key(age),

                                              key(card)

                                          );

1. select * from user where name="李先生" and adress="北京" and birthday="2011-11-11";

adress 和birthday列不走索引

(原因:违反最左前缀原则,顺序与复合索引顺序不一致)

 

2.select * from user where name="李先生"  and birthday >"2011-11-11"  and adress="北京" ;

adress 列不走索引

(原因:birthday 列的查询条件为范围查询,其右边的所有列都无法使用索引优化查询)

 

3.select * from user where name like "%李";

name 列不走索引

(原因:最左前缀匹配原则  ,like '李%' 走索引)

 

4.select * from user where name like "李%"  and birthday="2011-11-11";

birthday 列不走索引

(原因:like '李%' 也属于范围查询 与第二条一致)

 

5.select * from user where  age+10=30;

age 列不走索引

(原因:参与计算的列不走索引)

 

6.select * from user where LEFT(card,6)="231084";

card 列不走索引

(原因:使用函数的列不走索引)

 

7.select * from user where age=20 order by name asc , birthday desc;

order by 不能使用 索引扫描排序

(原因:虽然 order by  后的两个列 组成了最左前缀,但这个查询使用了两种不同的排序方向,索引列都是正序排列的)

 

8.select * from user where name like "李%" order  by  birthday;

order by 不能使用索引扫描

(原因:name 列使用了范围查询,复合索引其他的列不能使用索引)

9.如果类型是字符串,那一定要再条件中将数据使用引号引用起来,否则不使用索引

10.如果条件中有or  即使其中有条件索引也不会使用

(注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)

 

posted @ 2020-01-05 15:22  晋级在路上  阅读(859)  评论(0编辑  收藏  举报