LevelDB UWP 的迭代器和快照





0/5 (0投票)
更详细地了解 LevelDB UWP 中的迭代器和快照
引言
在我上一篇文章中,我介绍了LevelDB
的基础知识。我介绍了如何安装库以及使用基本的Get
、Put
、Delete
和Batch
操作。在这篇文章中,我将深入探讨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();
}
}
正如您所看到的,与任何其他事物一样,当您不再需要迭代器时,必须将其释放。迭代器具有Seek
、SeekToFirst
、SeekToLast
、Valid
、Next
和Prev
等方法来在记录之间导航(查看文档)。此外,它还提供Key
和Value
方法来读取切片本身。
使用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
}
结合WriteBatches
和Iterators
以及适当的同步可以产生强大的结果。你的想象力是你的极限。
结论
这完成了LevelDB
的基本用法。我将在以后的文章中介绍更高级的内容。您可以通过访问LevelDB UWP Wiki来查看详细文档。