索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。

索引的常见模型

哈希表、有序数组和搜索树。

哈希表

哈希表是一种以键-值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value。

哈希的思路很简单,把值放在数组里,用一个哈希函数把 key 换算成一个确定的位置,然后把 value 放在数组的这个位置。不可避免地,多个 key 值经过哈希函数的换算,会出现同一个值的情况。处理这种情况的一种方法是,拉出一个链表

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1161d24b-7b9d-4821-b240-6f05c28c0d53/Untitled.png

首先,将 ID_card_n2 通过哈希函数算出 N;然后,按顺序遍历,找到 User2。

需要注意的是,图中四个 ID_card_n 的值并不是递增的,这样做的好处是增加新的 User 时速度会很快,只需要往后追加。但缺点是,因为不是有序的,所以哈希索引做区间查询的速度是很慢的

哈希表这种结构适用于只有等值查询的场景

有序数组

有序数组在等值查询和范围查询场景中的性能就都非常优秀。

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fc239fd5-e5e8-4527-bf8c-4e38f1a6496f/Untitled.png

这时候如果你要查 ID_card_n2 对应的名字,用二分法就可以快速得到,这个时间复杂度是 O (log (N))。

如果仅仅看查询效率,有序数组就是最好的数据结构了。但是,在需要更新数据的时候就麻烦了,你往中间插入一个记录就必须得挪动后面所有的记录,成本太高

有序数组索引只适用于静态存储引擎

搜索树

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/50e36570-7c1d-4a81-ad1f-b92e7068d5e4/Untitled.png

二叉搜索树的特点是:每个节点的左儿子小于父节点,父节点又小于右儿子。这样如果你要查 ID_card_n2 的话,按照图中的搜索顺序就是按照 UserA -> UserC -> UserF -> User2 这个路径得到。这个时间复杂度是 O (log (N))。

当然为了维持 O (log (N)) 的查询复杂度,你就需要保持这棵树是平衡二叉树。为了做这个保证,更新的时间复杂度也是 O (log (N))。