1.1 B+ 树索引
B+ 索引在数据库的一个特点是高扇出性,因此树的高度一般都在 2 ~ 4 层。
数据库中的 B+ 树索引分为聚集索引和辅助索引(secondary index),前者叶子结点存放的是一整行的数据。
1.1.1 聚集索引
由图可知,对于 B+ 树索引,除了叶子结点,其他节点的列有主键列和指针列,并且按照主键排序。而在获取到叶子结点时,对于特定的行记录仍需要依据 Page Directory 进行二分查找。
1.1.2 辅助索引
通过辅助索引查找数据时,InnoDB 会遍历辅助索引并通过叶级别的指针获得指向主键索引的主键,然后通过主键索引来找到一个完整的行记录。
1.2 Cardinality 值
表示索引中不重复记录数量的估计值。需要注意的是这只是一个预估值,并不一定准确。
在实际应用中,Cardinality / n_rows_in_table 应尽可能接近1,表示选择性大,适合创建索引。
1.3 B+ 树索引的使用
1.3.1 联合索引
联合索引是指对表上的多个列进行索引。
CREATE TABLE t (
a INT,
b INT,
PRIMARY KEY(a),
KEY idx_a_b (a,b)
)ENGINE = INNODB
上述代码创建了一张 t 表,并且 idx_a_b 是联合索引。以下是索引内部的结果。
从上图可以看到基本是和单键值的 B+ 树是一致的,但是多键值中,每个键仍然是有序的,这个顺序取决于定义联合索引的顺序。
由图可以看出对于SELECT * FROM t WHERE a = XXX AND b = XXX
和 SELECT * FROM t WHERE a = XXX
都可以使用联合索引 (a,b) ,但是对于 SELECT * FROM t WHERE b = XXX
则不能使用该索引(单独的 b 不是有序的)。
此外,还可以发现如果使用联合索引的话,如果确定了 a ,那么 b 也是排序的。这意味着对于查询语句 SELECT …FROM t WHERE a = XXX ORDER BY b
是非常适合用联合索引的,因为如果使用主键索引 a 的话,还要对 b 进行一次排序。
1.3.2 覆盖索引
从辅助索引中就可以得到查询的记录,而不需要查询聚集索引中的记录。举个例子,假设表 t 中有 2 列,a 和 b ,其中,列 a 是主键列,列 b 是辅助索引。那么对于SELECT a FROM t WHERE b = XXX
就不会再到聚集索引中去找,因为辅助索引中已经知道了主键 a 的值。
1.3.3 Multi-Range Read 优化
Multi-Range Read 优化的目的是减少磁盘的随机访问,并且把随机访问转变为较为顺序的数据访问。MMR 优化适用于 range、ref 和 eq_ref 类型的查询。
在查询辅助索引的时候,首先根据得到的查询结果按照主键排序,再按照主键排序的顺序进行书签查找。这样做的好处是显而易见的:
- 减少缓冲池中页被替换的次数。
- 批量处理对键值的查询操作。
1.3.4 Index Condition Pushdown 优化
数据库在取出索引的同时,判断是否可以进行 WHERE 条件的过滤,也就是将 WHERE 的部分过滤操作放在了存储引擎层。ICP 优化支持 range、ref、eq_ref、ref_or_null 类型的查询。
1.4 全文检索
1.4.1 倒排索引
同 B+ 树索引一样,这也是一种索引结构。它在辅助表中存储了单词与单词自身在一个或多个文档中所在位置之间的映射。这通常利用关联数组实现,有 2 种表现形式:
- inverted file index,{单词,单词所在文档 ID}
- full inverted index,{单词,(单词所在文档 ID,文档中的具体位置)}