我有一个场景,我存储了大量第三方数据,供业务用户进行临时分析。使用多个自连接,投影和范围,大多数针对数据的查询都会很复杂。
在选择用于Azure DocumentDB的PartitionKey
时,我看到人们建议使用逻辑分隔符,例如TenantId,DeviceId等。
鉴于DocumentDB的并行特性,我很好奇它如何处理基于某种GUID或大整数的PartitionKey
,以便在大型读取期间,它将是高度分辨的。
考虑到这一点,我设计了一个包含两个集合的测试:
test-col-1
PartitionKey
是TenantId,大约有100个可能的值test-col-2
PartitionKey
是由第三方分配的符合“AB1234568”模式的唯一值。保证第三方在全球范围内独一无二。两个集合都设置为100,000 RU。
在我的实验中,我加载了大约2,000个文档的集合。每个文档大小约为20 KB,并且高度非规范化。每个文档都是一个订单,其中包含多个作业,每个作业都包含用户,价格等。
示例查询:
SELECT
orders.Attributes.OrderNumber,
orders.Attributes.OpenedStamp,
jobs.SubOrderNumber,
jobs.LaborTotal.Amount As LaborTotal,
jobs.LaborActualHours As LaborHours,
jobs.PartsTotal.Amount As PartsTotal,
jobs.JobNumber,
jobs.Tech.Number As TechNumber,
orders.Attributes.OrderPerson.Number As OrderPersonNumber,
jobs.Status
FROM orders
JOIN jobs IN orders.Attributes.Jobs
JOIN tech IN jobs.Techs
WHERE orders.TenantId = @TentantId
AND orders.Attributes.Type = 1
AND orders.Attributes.Status IN (4, 5)";
在我的测试中,我调整了以下设置:
ConnectionPolicy
ConnectionPolicy
ConnectionMode.Direct
,Protocol.Tcp
MaxDegreeOfParallelism
值MaxBufferedItemCount
使用EnableCrossPartitionQuery = true
查询带有GUID PartitionKey的集合。我正在使用C#和.NET SDK v1.14.0。
在我使用默认设置的初始测试中,我发现使用TentantId
作为PartitionKey查询集合的速度更快,平均 3,765 ms 与 4,680 ms相比在GUID键控的集合上。
当我使用ConnectionPolicy
将Direct
设置为TCP
时,我发现TenantID
个集合查询时间减少了近1000毫秒,平均值 2,865毫秒< / strong>而GUID集合增加了约800毫秒,平均 5,492毫秒。
当我开始使用MaxDegreeOfParellelism
和MaxBufferedItemCount
时,事情开始变得有趣。 TentantID
集合查询时间通常不受影响,因为查询不是交叉收集,但GUID集合显着加快,达到 450毫秒(MaxDegreeOfParellelism
的速度= 2000,MaxBufferedItemCount
= 2000)。
鉴于这些观察结果,为什么你不想让PartitionKey
尽可能广泛地?
答案 0 :(得分:3)
当我开始玩MaxDegreeOfParellelism和MaxBufferedItemCount时,事情开始变得有趣。 TentantID集合查询时间通常不受影响,因为查询不是交叉收集,但GUID集合显着加速,达到最快450毫秒的值( MaxDegreeOfParellelism = 2000,MaxBufferedItemCount = 2000)。
MaxDegreeOfParallelism可以设置ParallelOptions实例启用的最大并发任务数。据我所知,这是一个客户端并行性,它会占用您站点上的CPU /内存资源。
鉴于这些观察,为什么你不想让PartitionKey成为一个尽可能广泛的值?
对于写入操作,我们可以跨分区键进行扩展,以便使用您已配置的全部内容。对于读取操作,我们需要最小化跨分区查找以降低延迟。
此外,正如这份官方文件所述:
分区键的选择是您在设计时必须做出的重要决定。 您必须选择具有多种值的属性名称,并且具有访问模式。
最佳做法是使具有许多不同值的分区键(至少100s-1000s)。
要实现容器的完整吞吐量,必须选择一个分区键,以便在一些不同的分区键值之间均匀分配请求。
有关详细信息,请参阅How to partition and scale in Azure Cosmos DB和此频道9教程,了解Azure DocumentDB Elastic Scale - Partitioning。