MySQL索引

  在数据库中,对性能影响最大的包括数据库的锁策略、缓存策略、索引策略、存储策略、执行计划优化策略。

索引策略决定数据库快速定位数据的效率,存储策略决定数据持久化的效率。

一。索引注意事项

1.索引不存储null值。

      更准确的说,单列索引不存储null值,复合索引不存储全为null的值。索引不能存储Null,所以对这列采用is null条件时,因为索引上根本

没Null值,不能利用到索引,只能全表扫描。

     为什么索引列不能存Null值? 因为将索引列值进行建树,其中必然涉及到诸多的比较操作。

2.不适合键值较少的列(重复数据较多的列)。

     假如索引列TYPE有5个键值,如果有1万条数据,那么 WHERE TYPE = 1将访问表中的2000个数据块。

再加上访问索引块,一共要访问大于2000个的数据块。

    如果全表扫描,假设10条数据一个数据块,那么只需访问1000个数据块,既然全表扫描访问的数据块

少一些,肯定就不会利用索引了。

3.前导模糊查询不能利用索引(like '%XX'或者like '%XX%')

   假如有这样一列code的值为'AAA','AAB','BAA','BAB' ,如果where code like '%AB'条件,由于前面是

模糊的,所以不能利用索引的顺序,必须一个个去找,看是否满足条件。这样会导致全索引扫描或者全表扫

描。如果是这样的条件where code like 'A % ',就可以查找CODE中A开头的CODE的位置,当碰到B开头的

数据时,就可以停止查找了,因为后面的数据一定不满足要求。这样就可以利用索引了。

二。MySQL索引

  B-Tree索引具有范围查找和前缀查找的能力,对于有N节点的B树,检索一条记录的复杂度为O(LogN)。相当于二分查找。

Hash索引只能做等于查找,但是无论多大的Hash表,查找复杂度都是O(1)。显然,如果值的差异性大,并且以等值查找(=、

<、>、in)为主,Hash索引是更高效的选择,它有O(1)的查找复杂度。如果值的差异性相对较差,并且以范围查找为主,B树

是更好的选择,它支持范围查找。

不同的存储引擎,不同索引实现细节:MyISAM中数据行和索引是分开存放的,由于一个表可以有多个索引,这些索引全部都放在一个索引文件里面。
InnoDB存在表空间的概念,一个表空间有自己的索引和数据。
 

三。索引分类

1.主键索引

MySQL中主键必须唯一且不能有空值,因此在主键上的索引也是唯一索引。一个表上的唯一索引可以有多个,但主键只有一个。一般在建表的同时会创建
主键索引,InnoDB中,如果没有指定主键,会隐含性创建一个长度为6的索引。
 

2.唯一索引

唯一索引中允许有空值出现。建立唯一索引的语法如下:
CREATE UNIQUE INDEX indexName ON tablename(columnname(length)) 
如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。这么做的好处:
一是简化了MySQL对这个索引的管理工作,这个索引也因此而变得更有效率
二是MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了
 
 
3.普通索引
 
这种索引没有任何限制,可以有重复数据,也可以为空。建立普通索引的语法如下:
CREATE INDEX indexName ON tablename(columnname(length)) 
普通索引的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column = …)或排序条件(ORDER BY column)中
的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
对于varchar类型的字段,索引长度的选取很重要,不能太短起不到索引的效果,也不能太长浪费了存储空间。一般应小于varchar实际长度。
 

4.组合索引

当有多个查询条件时,可以采用组合索引,索引可以覆盖多个数据列,可以有选择地使用其中一个索引。如果查询操作只需要用到columnA数据列上的一个
索引,就可以使用复合索引INDEX(columnA, columnB)。不过,这种用法仅适用于在复合索引中排列在前的数据列组合。比如说,INDEX(A, B, C)可以
当做A或(A, B)的索引来使用,但不能当做B、C或(B, C)的索引来使用。这就是所谓的最左前缀原则。
 
 

四。注意事项

1、全列匹配
当where语句中涉及到多列,且都是精准匹配(=或者in)时,理论上我们应该注意字段的顺序,但mysql会帮我们优化,采用最左前缀匹配。
若需要查看一个语句是否有用索引可以在前面加上EXPLAIN关键字。
 
2、最左前缀匹配
select * from tablename where A=a and B=b and C=c and D=d
如果在A,B,D上建有索引,那么只在A,B上的索引才有效,D上的索引不会被用到。
 
3、如果中间某个字段没有索引,后面的索引不会生效。跟2类似,由于C上没有索引,索引D不会生效。可以在(C,D)上单独建一个辅助索引。
select * from tablename where A=a and B=b and  D=d这条语句,
如果在(A,B,C,D)四列上建有组合索引,A,B肯定能匹配上,由于没有按C进行查询,在D上只能按照where条件过滤,
如果C的取值少,可以用in替换这条SQL:select * from tablename where A=a and B=b and C in() and  D=d,这个索引可以合理地被利用。
 
4、某些like语句可以走索引,一般不推荐在sql中用like语句,稍不注意会导致全表扫描。对于title like 'keyword%'这种是可以用到索引的,
其他情况比如title like '%keyword',title like '_keyword'不能走索引
 
5、范围查询,范围查询可以用到索引,必须是最左前缀,范围列后面的索引用不到。一条语句中最好把范围列放最后,不要出现多个范围列。
6、函数表达式 不要在列上直接套用函数或者表达式,这样用不到索引。

 

相关
mysql 查询优化杂谈
原文地址:https://www.cnblogs.com/yuyutianxia/p/3841964.html