65.9K
CodeProject 正在变化。 阅读更多。
Home

LevelDB UWP 的迭代器和快照

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2016年3月13日

MIT

3分钟阅读

viewsIcon

13615

更详细地了解 LevelDB UWP 中的迭代器和快照

引言

在我上一篇文章中,我介绍了LevelDB的基础知识。我介绍了如何安装库以及使用基本的GetPutDeleteBatch操作。在这篇文章中,我将深入探讨LevelDB的迭代器和快照功能。

创建快照

快照是极其强大的构造,允许您为读取操作冻结特定的视图。快照为所有读取操作提供一致的只读视图。当从数据库读取值时,很可能其他DB对象的实例正在更改数据库。在某些情况下,您可能希望在特定时间点冻结数据库的快照。这就是Snapshot对象将帮助您的地方。由于Snapshot在您进行读取时必须保留一些额外的数据和资源,因此在完成操作后必须释放它。创建和释放快照非常简单。

using (var snapshot = db.GetSnapshot())
{
    ...
}

如果您没有在代码中编写using块,请确保调用snapshot.Dispose()

使用快照

每个ReadOption对象都可以接受一个Snapshot属性,并且每个读取操作都需要您传递ReadOption对象。一旦您拥有快照,您可以像以下代码所示那样使用它。

using (var snapshot = db.GetSnapshot())
{
    var val = db.Get(new ReadOptions { Snapshot = snapshot }, Slice.FromString("foo"));
}

迭代器

当然,当您想要迭代存储在键值存储中的数据时,需要迭代器。我现在不会详细介绍比较器,但默认情况下(LevelDB UWP)按键字节以字典序排序数据。可以使用比较器自定义此行为,但这不在本文的讨论范围之内。因此,总结默认键顺序的最佳方法是想象我的键值存储插入了以下键值对。

db.Put(Slice.FromString("b"), Slice.FromString("Two"))
db.Put(Slice.FromString("d"), Slice.FromString("Three"))
db.Put(Slice.FromString("a"), Slice.FromString("One"))

它将按以下顺序存储:a => One, b => Two, d => Three。这意味着从头到尾迭代,您将按a, b, c的顺序遇到键,因为a < b < c。记住这一点,让我们创建一个迭代器来迭代数据库中的所有键值对。

using (var itr = db.NewIterator(new ReadOptions()))
{
    itr.SeekFirst();
    while (itr.Valid())
    {
        byte[] key = itr.Key().ToByteArray();
        byte[] val = itr.Value().ToByteArray();
        itr.Next();
    }
}

正如您所看到的,与任何其他事物一样,当您不再需要迭代器时,必须将其释放。迭代器具有SeekSeekToFirstSeekToLastValidNextPrev等方法来在记录之间导航(查看文档)。此外,它还提供KeyValue方法来读取切片本身。

使用Seek,您可以执行一些强大的操作,例如迭代键为X..Y的记录,例如

using (var itr = db.NewIterator(new ReadOptions()))
{
    itr.Seek(Slice.FromString("record001"));
    while (itr.Valid())
    {
        var keySlice = itr.Key();
        if (keySlice.ToString() == "record007") break;
        // use keySlice
        itr.Next();
    }
}

反向顺序也可以这样做。

using (var itr = db.NewIterator(new ReadOptions()))
{
    itr.Seek(Slice.FromString("record007"));
    while (itr.Valid())
    {
        var keySlice = itr.Key();
        if (keySlice.ToString() == "record001") break;
        // use keySlice
        itr.Prev();
    }
}

请记住,反向迭代是一个代价较大的操作,因此速度稍慢。尽可能尝试使用正向迭代。

组合快照和迭代器

我们可以将迭代器与快照融合,以创建真正强大的功能,例如在发生变异时获取特定时间点的键值对集(类似于MVCC)。它再简单不过了。

using (var snapshot = db.NewSnapshot())
using (var itr = db.NewIterator(new ReadOptions({ Snapshot = snapshot })))
{
  // use itr
}

结合WriteBatchesIterators以及适当的同步可以产生强大的结果。你的想象力是你的极限。

结论

这完成了LevelDB的基本用法。我将在以后的文章中介绍更高级的内容。您可以通过访问LevelDB UWP Wiki来查看详细文档。

© . All rights reserved.