上文说的很抽象,我们回来看看我们的问题 。这次不用傻傻的数字了,想象一下前表中代表某人的国家的字符串 。假设你有个树包含表中的列『country』:
- 如果你想知道谁在 UK 工作
- 你在树中查找代表 UK 的节点
- 在『UK 节点』你会找到 UK 员工那些行的位置
B+树索引
查找一个特定值这个树挺好用,但是当你需要查找两个值之间的多个元素时,就会有大麻烦了 。你的成本将是 O(N),因为你必须查找树的每一个节点,以判断它是否处于那 2 个值之间(例如,对树使用中序遍历) 。而且这个操作不是磁盘I/O有利的,因为你必须读取整个树 。我们需要找到高效的范围查询方法 。为了解决这个问题,现代数据库使用了一种修订版的树,叫做B+树 。在一个B+树里:
- 只有最底层的节点(叶子节点)才保存信息(相关表的行位置)
- 其它节点只是在搜索中用来指引到正确节点的 。
文章插图
你可以看到,节点更多了(多了两倍) 。确实,你有了额外的节点,它们就是帮助你找到正确节点的『决策节点』(正确节点保存着相关表中行的位置) 。但是搜索复杂度还是在 O(log(N))(只多了一层) 。一个重要的不同点是,最底层的节点是跟后续节点相连接的 。
用这个 B+树,假设你要找40到100间的值:
- 你只需要找 40(若40不存在则找40之后最贴近的值),就像你在上一个树中所做的那样 。
- 然后用那些连接来收集40的后续节点,直到找到100 。
然而还有新的问题(又来了!) 。如果你在数据库中增加或删除一行(从而在相关的 B+树索引里):
- 你必须在B+树中的节点之间保持顺序,否则节点会变得一团糟,你无法从中找到想要的节点 。
- 你必须尽可能降低B+树的层数,否则 O(log(N)) 复杂度会变成 O(N) 。
想了解更多细节,你可以看看 Wikipedia 上这篇关于B+树的文章 。如果你想要数据库中实现B+树的例子,看看MySQL核心开发人员写的这篇文章 和 这篇文章 。两篇文章都致力于探讨 innoDB(MySQL引擎)如何处理索引 。
哈希表
我们最后一个重要的数据结构是哈希表 。当你想快速查找值时,哈希表是非常有用的 。而且,理解哈希表会帮助我们接下来理解一个数据库常见的联接操作,叫做『哈希联接』 。这个数据结构也被数据库用来保存一些内部的东西(比如锁表或者缓冲池,我们在下文会研究这两个概念) 。
哈希表这种数据结构可以用关键字来快速找到一个元素 。为了构建一个哈希表,你需要定义:
- 元素的关键字关键字的哈希函数 。关键字计算出来的哈希值给出了元素的位置(叫做哈希桶) 。关键字比较函数 。一旦你找到正确的哈希桶,你必须用比较函数在桶内找到你要的元素 。
我们来看一个形象化的例子:
文章插图
这个哈希表有10个哈希桶 。因为我懒,我只给出5个桶,但是我知道你很聪明,所以我让你想象其它的5个桶 。我用的哈希函数是关键字对10取模,也就是我只保留元素关键字的最后一位,用来查找它的哈希桶:
推荐阅读
- 如何挑选黑豆
- 不是夫妻合租房犯罪吗
- 医保断缴三个月余额清零?员工可自愿放弃社保?这些谣言别再信了
- 手串颗数大有讲究,千万别戴错了
- “禁止长时间停车”,到底指的是几分钟?交警:最后再说一遍
- 太热了!别再披头散发了,这4款发型够美够清凉
- 没钱还信用卡有什么解决办法
- 信用卡过期卡怎么处理
- 信用卡逾期被注销怎么还钱
- 如何找回抖音私聊记录