索引是提升数据库性能最直接的手段,如果没有索引,mysql必须从第1条记录开始然后读完整个表直到找出相关的行.表越大花费的时间越多.
mysql中的MyISAM和InnoDB存储引擎的表默认创建的都是BTREE索引,mysql支持前缀索引,即对索引字段的前N个字符创建索引.mysql也支持全文本(FULLTEXT)索引,该索引可以用于全文搜索.也可以为空间列类型创建索引,但是只有MyISAM存储引擎支持空间类型索引,且索引的字段必须是非空的.MEMORY存储引擎默认使用HASH索引,但也支持BTREE索引.
索引在设计的时候可以遵循一些原则,在创建索引的时候考虑符合这些原则可以提升索引的使用效率,更高效地使用索引.
1.最适合添加索引的列是出现在where字句中的列,而不是select关键字后面的列.
2.添加索引的列的''可区分度''一定要高,举个例子:每个用户的电话号码一般来说都不一样,这一列就很适合作为索引列,而性别一般来说就两种,无论搜索那个值,都会得出大约一半的行,那么对此列进行索引就没有多大用处.
3.使用短索引,如果对字符串进行索引,应该指定一个前缀长度,只要有可能就应该这样做,例如:如果有一个char(200)的列,如果在前10个或者20个字符内,多数值是唯一的,那么就不要对整个列进行索引.对前10个20个字符进行索引能够节省大量索引的空间,也可能会使查询更快.较小的索引设计的磁盘I/O较少,较短的值比较起来更快.更为重要的是,对于较短的键值,索引高速缓存中的块能容纳更多的键值,因此,mysql也可以在内存中容纳更多的值,这样就增加了找到行而不用读取索引中较多快的可能性.
4.利用最左前缀.在创建一个n列的索引时,实际是创建了mysql可利用的n个索引,多列索引可起几个索引的作用,因为可利用索引中最左边的列集来匹配行.这样的列集称为最左前缀.
5.不要过度索引.索引并不是越多越好,每个额外的索引都要占用额外的磁盘空间,并降低操作的性能.在修改表内容的时候,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长.如果一个索引很少使用或从不使用,建议删除该索引.当索引太多时,也可能会使mysql选择不到所要使用的最好索引,只保持所需的索引有利于查询优化.
6.对于InnoDB存储引擎的表,如果有明确定义的主键,则按照主键顺序保存.如果没有主键,但是有唯一索引,那么就是按照唯一索引的顺序保存.如果既没有主键又没有唯一索引,那么表中会自动生成一个内部列,按照这个列的顺序保存.按照主键或者内部列进行访问时最快de,所以InnoDB表尽量选择自己指定的主键,当表中同时有几个列都是唯一的,都可以作为主键的时候,要选择最常作为访问条件的列作为主键,提高查询效率.另外,还需要注意,InnoDB表的普通索引都会保存主键的键值,所以主键要尽可能选择较短的数据类型,可以有效地减少索引的磁盘占用,提高索引的缓存效果.
HASH索引的检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引,但HASH索引的特性也带来了很多限制,主要有以下几点:
1.HASH索引只能满足'=' , 'in' 的查询,不能使用范围查询.由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样.
2.优化器不能使用 HASH 索引来加速 ORDER BY 操作. 由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来优化任何排序运算.
3.Hash 索引不能利用部分索引键查询.对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用.
对于BTREE索引,当使用>,<,>=,<=,between,!=或者like'pattern'(其中pattern不以通配符开始)操作符时,都可以使用相关列上的索引.