在之前的介绍中,学习了如何安装库以及如何使用基本的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方法来读取切片本身。
using(var snapshot = db.NewSnapshot())
using(var itr = db.NewIterator(new ReadOptions({ Snapshot = snapshot })))
{
// 使用 itr
}