Azure cosmosdb 使用CosmosDB跨分区查询批量操作的最有效方法

Azure cosmosdb 使用CosmosDB跨分区查询批量操作的最有效方法,azure-cosmosdb,Azure Cosmosdb,我有一个跨分区查询,它依次返回每个分区的行,这是有意义的,所有分区1的结果,所有分区2的结果等等 对于返回的每一行,我都需要执行一个操作,可以是删除或更新 有太多的记录,无法将它们全部读入然后执行操作,因此我需要流式输入结果并同时执行操作 我遇到的问题是我的RU很快就用完了,因为我的操作依次在每个分区上运行,并且单个分区分配了十分之一的RU 我可以在FeedOptions中指定PartitionKey,但这对我没有帮助,因为我不知道该键是什么 我的问题看起来像 select r.* from r

我有一个跨分区查询,它依次返回每个分区的行,这是有意义的,所有分区1的结果,所有分区2的结果等等

对于返回的每一行,我都需要执行一个操作,可以是删除或更新

有太多的记录,无法将它们全部读入然后执行操作,因此我需要流式输入结果并同时执行操作

我遇到的问题是我的RU很快就用完了,因为我的操作依次在每个分区上运行,并且单个分区分配了十分之一的RU

我可以在
FeedOptions
中指定
PartitionKey
,但这对我没有帮助,因为我不知道该键是什么

我的问题看起来像

select r.* from r where r.deleted 
分区
位于名为
容器

假设我有以下项目

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
我使用一个
ActionBlock
来允许我在返回的每一行上旋转两个线程来执行我的操作,因此我在
jam
pickles
上工作,然后
cookies
sweets
上执行
jam
pickles

我希望将结果返回为:

jam      <--- stored in partition 5
cookies  <--- stored in partition 8
sweets   <--- stored in partition 9
pickles  <--- stored in partition 5

jam您需要设置
MaxDegreeOfParallelism
,这是
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个返回实际数据


您可以运行query
从c中选择DISTINCT c.container,其中c.deleted=true
来选择包含已删除项的所有分区,然后运行存储过程,为每个分区在批量文档中删除。示例可能有误导性,我可以读取所有数据,问题是,它按顺序使用每个分区上的所有RU,而不是在初始选择中为每个分区返回几行。因此,分区在相同分区密钥范围内的每个文档都位于相同的物理位置。这就是为什么在使用跨分区查询时,首先会看到一个物理位置的结果,然后是其他位置的结果。为了解决您的问题,您可以编写自己的管理器,将负载分配到客户端的分区上。cosmos只需自己处理分区,这对于正常使用很好,这只是我的一次性批量操作受到阻碍。我刚刚重新阅读了其中一个文档,我想我需要这样做(我确信我以前尝试过:)。我设置了
enableCrospartitionQuery
选项,并使用fiddler查看发生了什么,我可以看到它发出10个请求,并设置了一个头,看起来像是分区要做的事情——我已经在下面做了经验回答,第一部分(看起来像Base64字符串)是集合的内部id(aka
\u rid
)。对该集合的所有查询都应该是相同的。我希望您不介意我编辑您的答案(如果您这样做,请随时回复)。在评论中嵌入图片并不容易,我不想在没有足够上下文的情况下发布单独的答案,也不想复制你的内容。
x-ms-documentdb-query-enablecrosspartition: True
x-ms-documentdb-query-parallelizecrosspartitionquery: True
x-ms-documentdb-populatequerymetrics: False
x-ms-documentdb-partitionkeyrangeid: QQlvANNcKgA=,3