概述
所有的MySql列类型(字段类型)都可以被索引,对相关列使用索引是提高SELECT操作性能的最佳途径。每种存储引擎对每个表至少支持16个索引,总索引长度至少为256字节。
MyISAM和InnoDB存储引擎的表默认创建的都是BTREE索引。MySQL支持前缀索引的长度跟储存引擎相关,对于MyISAM存储引擎的表,索引的前缀长度可以达到1000字节长,而对于InnoDB存储引擎的表,索引的前缀长度最长是767字节。请注意前缀的限制应以字节为单位进行测量,而CREATE TABLE语句中的前缀长度解释为字符数。
设计原则
场景 | 适合创建 | 不适合创建 |
查询语句 | WHERE子句中的列,连接子句中指定的列,排序、统计或分组的列 | SELECT选择列表中的列 |
查询条件 | = 和 IN 的判断条件,OR 方式需要视具体情况 | 负向查询,如 !=、NOT IN等,参与计算的列,如from_unixtime(create_time) = ’2018-08-29’ |
值的分布 | 列的区分度越高,效果越好。如存放出生日期的列具有不同值,很容易区分各行 | 列的区分度低的。如只包含(M, F)两个值的性别,因为不管搜哪个值,都会得出大约一半的行 |
表的记录 | 数据记录较多,大概在300行以上 | 数据记录较少 |
频繁操作 | 频繁进行查询的列 | 频繁增删改的列 |
LIKE语句 | 后模糊匹配(百分号在后) | 前模糊匹配(百分号在前) |
字段类型 | 主键、外键 | TEXT和BLOB等文本字段甚至超长字段 |
字符串列 | 指定前缀长度。如一个CHAR(200)的列,在前20个字符内多数值是唯一的时候 | 对整列且字符长度较大 |
NULL值 | 不含有NULL值 | 含有NULL值 |
索引数量 | 缺少或很少索引 | 过度索引,很少或从不使用的索引。 |
使用注意
排序索引
MySQL查询只使用一个索引,因此如果WHERE子句中已经使用了索引的话,那么ORDER BY中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
复合索引
比如有一条语句是这样的:select * from users where area=’beijing’ and age=22; 如果我们是在 area 和 age 上分别创建单个索引的话,由于MySQL查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效率,但是如果在 area、age 两列上创建复合索引的话将带来更高的效率。如果我们创建了(area, age, salary)的复合索引,那么其实相当于创建了(area, age, salary)、(area, age)、(area)三个索引,这被称为最佳左前缀特性。因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。
最左前缀
MySQL会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如 a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
适度索引
每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长。此外,MySQL在生成一个执行计划时,要考虑各个索引,这也要花费时间。创建多余的索引给查询优化带来了更多的工作。索引太多,也可能会使MySQL选择不到所要使用的最好所要。