azure-cosmosdb - 使用 CosmosDB 跨分区查询以进行批量操作的最有效方法
问题描述
我有一个跨分区查询,它依次返回每个分区的行,这是有道理的,所有分区 1 的结果,所有分区 2 的结果等等。
对于返回的每一行,我需要执行一个操作,可以是删除或更新。
有太多记录无法全部读取然后执行操作,因此我需要输入结果并同时执行操作。
我遇到的问题是我很快就用完了 RU,因为我的操作依次在每个分区上运行,并且单个分区分配了十分之一的 RU。
我可以PartitionKey
在中指定 aFeedOptions
但这对我没有帮助,因为我不知道密钥是什么。
我的查询看起来像
select r.* from r where r.deleted
在partition
一个叫做的字段上container
想象一下我有以下物品
container|title |deleted
jamjar |jam |true <--- stored in partition 5
jar |pickles |true <--- stored in partition 5
tin |cookies |true <--- stored in partition 8
tub |sweets |true <--- stored in partition 9
我做select r.title from r where r.deleted
我的查询将按以下顺序返回行
jam <--- stored in partition 5
pickles <--- stored in partition 5
cookies <--- stored in partition 8
sweets <--- stored in partition 9
我使用 anActionBlock
来允许我启动 2 个线程以对返回的每一行执行我的操作,因此我继续工作,jam
然后pickles
在执行操作时消耗来自分区 5 的 RU和cookies
sweets
jam
pickles
我希望结果返回为:
jam <--- stored in partition 5
cookies <--- stored in partition 8
sweets <--- stored in partition 9
pickles <--- stored in partition 5
对于正常的 API 调用,我们总是知道container
,这是批量和非常不频繁的删除的要求。
如果知道分区的数量并且可以将分区号提供给查询就可以了,我很乐意发出 10 个查询并将其视为 10 个单独的作业。
解决方案
您需要设置MaxDegreeOfParallelism
which 是的一部分FeedOptions
:
FeedOptions queryOptions = new FeedOptions
{
EnableCrossPartitionQuery = true,
MaxDegreeOfParallelism = 10,
};
它将为每个分区创建一个客户端线程,如果您检查 HTTP 标头,您可以看到发生了什么
x-ms-documentdb-query-enablecrosspartition: True
x-ms-documentdb-query-parallelizecrosspartitionquery: True
x-ms-documentdb-populatequerymetrics: False
x-ms-documentdb-partitionkeyrangeid: QQlvANNcKgA=,3
注意QQlvANNcKgA=,3你会看到其中的 10 个,从,0到,9我怀疑第一部分是一些页面跟踪,第二部分是分区
请参阅文档并行查询执行
这是 Fiddler 中 3 个查询的时间线视图:
MaxDegreeOfParallelism = 10
:较慢且不太并行,而线程和连接正在旋转(您可以在左侧列表中看到 5 次额外的 SSL 握手,以及在时间轴中设置的“绿色”的最后 5 个请求之前的间隙)。还有 2 个(出于某种原因)请求获取集合的 PK 范围MaxDegreeOfParallelism = 10
(再次):几乎最佳并行。PK 范围信息似乎是从先前的请求中缓存的,并在此处重用,而不会发出任何无关的请求。MaxDegreeOfParallelism = 0
: 完全顺序。
有趣的是,这些请求没有指定x-ms-documentdb-partitionkeyrangeid
标头。
使用 DocumentClient v2.x针对具有6 个物理分区的集合运行查询。
另请注意,每个查询都会触发 7 个请求,第一个是“查询计划请求”(不可并行化),而以下 6 个返回实际数据。
推荐阅读
- r - 嵌套ifelse,返回'else'的原始值?
- javascript - 我如何在 vanila javascript 中制作外部可点击的 div
- android - RecyclerView 的空数据集指示器未显示
- javascript - 当我在 Raspberry Pi 上将 Selenium 与 Python 和 Geckodriver 一起使用时,Javascript 未启用
- c# - 如何使用多个 ViewModel 在 ASP.NET 中添加自定义年龄验证
- typescript - 从由参数值确定的联合返回类型返回单个类型
- tfs - 如何在 Wiki 中创建到存储库文件的链接
- flutter - Flutter中用自定义计数器函数替换Uuid
- javascript - RCT_EXPORT_METHOD 不向 NativeModules 导出任何内容
- javascript - 通过 Chrome/Edge 在特定网页上进行静默打印