通过建立索引可以有效的提高查询性能。索引也分为很多种(聚集、非聚集、联合索引等),数据结构主要有哈希索引和B+树等,哈希索引在单个查询性能上很强大,但不适合做范围查询。以下讨论主要是建立在B+树索引上面的。
索引一般采用B+树的数据结构,B+树是一个有序的树形结构,每个父节点可以有多个子节点,子节点之间也通过指针相互连接。
建立索引需要注意的地方:
a. 尽量不要在字段类型长度太大的字段上建立索引,例如 text;
b. 不要在取值范围太小的字段建立索引;例如 性别;
c. 不要在不经常进行where查询过滤的字段建立索引;
d. 一个表不能建立过多的索引;维护索引需要消耗资源;
e. 数据量太少也不需要建索引,有时候反而性能更低。当然这点性能可以忽略不计;
那么如何选择一个有效、合适的索引呢?首先让我们先了解一下它们。
1、聚集索引(也叫 聚簇索引、主键索引)
一个表只能拥有一个聚集索引,而且是建立在主键上面的,主键一般采用自增ID和GUID等方式。自增ID由于是有序的,而且占用字节较少。所以在性能和空间上都比较有优势。
表中的数据保存在聚集索引的叶子节点中。在利用聚集索引做查询的时候只需要根据索引字段找到对应的节点就可以查询到相应的数据。因为索引是有序的。 所以在范围查找的效率上也是很高的。只需要找到第一个节点和最后一个节点。其次可以利用索引字段进行order by 和group by操作,效率都是很高的。
2、 非聚集索引(也叫 非聚簇索引、二级索引)
一个表只能拥有多个非聚集索引,非聚集索引的叶子节点只保存聚集索引的索引字段值(主键列发的值)。
所以在利用非聚集索引做查询的时候通常会涉及到回表操作;这是因为在根据非聚集索引中查询只能得到主键列的值,然后需要根据主键列的值去查询聚集索引,最后才能得到我们想要的数据。
有时候也是可以不需要回表操作的, 比如:select id from table where index=1 ; 这是因为在非聚集索引中已经能获取到我们想要的数据了,这种方式被称为覆盖索引。
3、 联合索引
一个索引中可以包含多个字段,这种索引就叫做联合索引。
联合索引需要注意的就是字段顺序问题。在查询里面必须要使用联合索引中的第一个字段;
例如:索引包含三个字段(name,age,number);
select * from table where name ="小熊" ; --走索引
select * from table where name like "小%" ; --走索引
select * from table where age=18; --不走索引
如果查询结果中也只包含这三列是不用做回表查询的:例如select name,age,number from table where name ="小熊" ;
利用覆盖索引可以减少树的搜索次数,提高查询性能。
4、 普通索引和唯一索引
4.1 查询方面(唯一索引更佳,但差距非常小)
a. 普通索引:在查找到第一条记录后还需要查找下一条记录,直到遇到不满足条件的记录为止;由于MySql读取是根据数据页来读取的(16KB),所以普通索引在查询过程中可能需要读取多个数据页;
b. 唯一索引:由于字段值的唯一性,查找到第一个满足条件的记录后就可以停止查询;更适合做查询操作
4.2 更新(普通索引更佳)
a. 普通索引:由于普通索引在更新是时候是可以利用change buffer来提高性能的,但对于更新后立刻查询的业务场景应该关闭change buffer;否则会增加chang buffer的维护代价。更适合做更新操作
b. 唯一索引:唯一索引的更新不能使用change buffer。而且每次更新操作的时候先要判断是否已经存在相同的字段值。相对普通索引来讲增加了数据页的读取和判断操作。