常见索引模型
哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value。哈希的思路很简单,把值放在数组里,用一个哈希函数把key 换算成一个确定的位置,然后把 value 放在数组的这个位置。不可避免地,多个 key 值经过哈希函数的换算,会出现同一个值的情况。处理这种情况的一种方法是,拉出一个链表。哈希表这种结构适用于只有等值查询的场景。
有序数组在等值查询和范围查询场景中的性能就都非常优秀,有序数组索引只适用于静态存储引擎。
二叉搜索树:每个节点的左儿子小于父节点,父节点又小于右儿子,查询时间复杂度O(log(N)),更新时间复杂度O(log(N))。
InnoDB中的索引模型:B+Tree
索引类型:主键索引、非主键索引
主键索引的叶子节点存的是整行的数据(聚簇索引),非主键索引的叶子节点内容是主键的值(二级索引)。
主键索引和普通索引的区别:主键索引只要搜索ID这个B+Tree即可拿到数据。普通索引先搜索索引拿到主键值,再到主键索引树搜索一次(回表)。
索引维护:当插入的数据所在数据页满了,按照B+Tree算法,新增加一个数据页,叫做页分裂,会导致性能下降。空间利用率降低大概50%。当相邻的两个数据页利用率很低的时候会做数据页合并,合并的过程是分裂过程的逆过程。从性能和存储空间方面考量,自增主键往往是更合理的选择。
覆盖索引
因为普通索引上存储的是主键的值,所以每次使用普通索引查询行的所有数据的时候都会回表。但是只查询主键ID值的时候就不会发生回表操作了,因为普通索引上存储的是主键ID的值,这个过程称为覆盖索引。
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
联合索引
举个例子:假如我们有张身份信息表,如果有根据身份证号查询身份信息的需求,我们只要在身份证号字段上建立索引就够了。
如果现在有一个高频请求,要根据市民的身份证号查询他的姓名,这个联合索引就有意义了。它可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。
当使用多个普通索引的时候,我们就要建立多个索引,使用查询条件的时候每个索引都会发生回表操作,这个时候我们就可以用到联合索引了。
在建立联合索引的时候,如何安排索引内的字段顺序。
B+ 树这种索引结构,可以利用索引的“最左前缀”,来定位记录。
第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。
MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。