现在你已经知道 LSM 树的组织过程了,我们可以来看,LSM 树是如何完成检索的。
因为同时存在 C0 和 C1 树,所以要查询一个 key 时,我们会先到 C0 树中查询。如果查询到了则直接返回,不用再去查询 C1 树了。
而且,C0 树会存储最新的一批数据,所以 C0 树中的数据一定会比 C1 树中的新。因此,如果一个系统的检索主要是针对近期数据的,那么大部分数据我们都能在内存中查到,检索效率就会非常高。
那如果我们在 C0 树中没有查询到 key 呢?这个时候,系统就会去磁盘中的 C1 树查询。在 C1 树中查到了,我们能直接返回吗?如果没有特殊处理的话,其实并不能。你可以先想想,这是为什么。
我们先来考虑一种情况:一个数据已经被写入系统了,并且我们也把它写入 C1 树了。但是,在最新的操作中,这个数据被删除了,那我们自然不会在 C0 树中查询到这个数据。可是它依然存在于 C1 树之中。
这种情况下,我们在 C1 树中检索到的就是过期的数据。既然是过期的数据,那为了不影响检索结果,我们能否从 C1 树中将这个数据删除呢?删除的思路没有错,但是不要忘了,我们不希望对 C1 树进行随机访问。这个时候,我们又该怎么处理呢?
我们依然可以采取延迟写入和批量操作的思路。对于被删除的数据,我们会将这些数据的 key 插入到 C0 树中,并且存入删除标志。如果 C0 树中已经存有这些数据,我们就将 C0 树中这些数据对应的 key 都加上删除标志。
这样一来,当我们在 C0 树中查询时,如果查到了一个带着删除标志的 key,就直接返回查询失败,我们也就不用去查询 C1 树了。在滚动归并的时候,我们会查看数据在 C0 树中是否带有删除标志。如果有,滚动归并时就将它放弃。这样 C1 树就能批量完成「数据删除」的动作。