4

在可靠集合(特别是 IReliableDictionary)中,实现“常见”查询的一种方法是更新二级字典,该字典以特定方式在枚举中对键进行排序。对于大型数据集,我想避免在.

为了实现这一点,我想实现某种延续令牌,调用者可以在请求数据时提供给我。我目前正在通过首先生成一个有序枚举并返回前 n 个项目来实现这一点,其中 n = MAX_PAGE 大小。 延续本质上是 n 个项目列表中的最后一个键。下次调用者传入 continuation 令牌时,我会使用 filter 函数生成有序可枚举,指定 key 应该大于 continuation

这有两个问题(我可以看到):

  1. 集合可能会在调用者第一次请求页面和后续请求之间发生变化。这一点,我不确定我是否可以避免,因为无论谁试图翻阅数据,都需要能够随时更新集合。
  2. 我不确定如何使用过滤器功能。我假设由于开发人员可以过滤任何内容,因此GetEnumerableAsync() 方法必须在返回 enumerable 之前提供字典中的所有键。对于足够大的数据集,这似乎很慢。

有没有规定的方法来分页这样的数据? 我开始觉得我可能会在我的一些用例中使用 Reliable Collections 找出错误的树。

4

2 回答 2

5

构建二级索引的一种方法是使用Notifications。使用具有引用类型 TKey 和 TValue 的通知,您可以维护二级索引,而无需创建 TKey 或 TValue 的任何副本。

如果需要二级索引提供快照隔离,那么二级索引选择的数据结构必须实现多版本并发控制。

如果您没有这样的数据结构来托管二级索引,另一种选择是在分页客户端调用中保持事务和枚举实时。这样,您可以使用 Reliable Dictionary 的内置快照支持来提供对数据的分页一致扫描,而不会阻塞写入。在这种情况下,令牌将是TransactionId,允许您的服务找到MoveNextAsync上的相关枚举。使用此选项的缺点是 Reliable Dictionary 将无法修剪由可能长时间运行的快照事务保持可见的旧版本值。

为了减轻上述缺点,您可能希望限制正在进行的快照事务的数量以及客户端在您的服务处理枚举和相关的读取事务之前完成分页枚举的时间。

当使用带有键过滤器的CreateEnumerableAsync时,Reliable Dictionary 将为每个键调用过滤器,以查看它是否满足自定义过滤器。由于今天 TKeys 始终保存在内存中,因此对于大多数关键过滤器,我们在这里没有看到问题。枚举中最昂贵的部分往往是从磁盘检索分页值。

于 2016-12-08T21:45:46.320 回答
0

我有一个类似的问题,它还涉及对来自多个分区的数据进行过滤和排序。

我的计划是使用通知在非分区状态服务中构建索引视图。在这里,我将有多个具有不同键的字典,其中每个键是一个或多个可以过滤或排序的属性,值是一个排序的 ID 列表。

基本上,我计划对这些键进行搜索、排序和分页,然后在最后一步,我使用需要返回到原始分区的页面的 ID,并从那里获取这些 ID 的完整数据(这可以也可以从不同的无状态服务完成)。

此方法不提供数据一致性,因为查询的数据可以在后续分页之间发生变化。

它一定比有快照和延续令牌的要慢,但也许值得一试。

于 2017-09-20T09:25:59.873 回答