我们正在使用配置有 120K RU 的 CosmosDB Graph API 实例。我们使用 /partition_key
属性设置了一致的分区结构。
使用 Gremlin 查询图表时,我们注意到与其他查询相比,某些查询使用的 RU 数量过高。查询本身是相同的,但对于 partition_key
值本身而言。
例如,以下查询花费 23.25 RU:
g.V().has('partition_key', 'xxx')
而具有不同 partition_key
值的相同查询花费 4.14 RU:
g.V().has('partition_key', 'yyy')
查看两个查询的 .exectionProfile()
结果;它们看起来很相似。
昂贵的查询,花费 23.25 RU (xxx
):
[
{
"gremlin": "g.V().has('partition_key', 'xxx').executionProfile()",
"activityId": "ec181c9d-59a1-4849-9c08-111d6b465b88",
"totalTime": 12,
"totalResourceUsage": 19.8,
"metrics": [
{
"name": "GetVertices",
"time": 12.324,
"stepResourceUsage": 19.8,
"annotations": {
"percentTime": 98.78,
"percentResourceUsage": 100
},
"counts": {
"resultCount": 1
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 1,
"size": 848,
"storageCount": 1,
"storageSize": 791,
"time": 12.02,
"storeResourceUsage": 19.8
}
]
},
{
"name": "ProjectOperator",
"time": 0.15259999999999962,
"stepResourceUsage": 0,
"annotations": {
"percentTime": 1.22,
"percentResourceUsage": 0
},
"counts": {
"resultCount": 1
}
}
]
}
]
花费 4.14 RU (yyy
) 的廉价查询:
[
{
"gremlin": "g.V().has('partition_key', 'yyy').executionProfile()",
"activityId": "841e1c37-471c-461e-b784-b53893a3c349",
"totalTime": 6,
"totalResourceUsage": 3.08,
"metrics": [
{
"name": "GetVertices",
"time": 5.7595,
"stepResourceUsage": 3.08,
"annotations": {
"percentTime": 98.71,
"percentResourceUsage": 100
},
"counts": {
"resultCount": 1
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 1,
"size": 862,
"storageCount": 1,
"storageSize": 805,
"time": 5.4,
"storeResourceUsage": 3.08
}
]
},
{
"name": "ProjectOperator",
"time": 0.07500000000000018,
"stepResourceUsage": 0,
"annotations": {
"percentTime": 1.29,
"percentResourceUsage": 0
},
"counts": {
"resultCount": 1
}
}
]
}
]
两个查询的结果都返回大约相同大小的单个顶点。
有人可以帮忙解释一下为什么会这样吗?为什么其中一个比另一个贵得多?关于 Cosmos DB 分区是否有某些方面我不明白?
编辑 1:
我们还通过添加其他查询参数(例如 id
和 label
)进行了一些实验。 id
子句确实将昂贵的查询成本从约 23 RU 降低到约 4.57 RU。这种方法的问题在于,通常它会降低所有其他查询的效率(即增加 RU)。
例如,其他查询(如本票中的快速查询)从 ~4.14 RU 增加到 ~4.80 RU,并添加了 id
子句。所以这实际上并不可行,因为 99% 的查询都会变得更糟。我们需要找到根本原因。
最佳答案
您描述的“问题”可能与物理分区 (PP) 和逻辑分区 (LP) 的大小边界有关。 Cosmos DB 允许基于其 partitioning architecture 进行“无限”扩展。但扩展性能和数据增长很大程度上取决于逻辑分区策略。 Microsoft 强烈建议使用尽可能细化的 LP key ,以便数据在 PP 之间均匀分布。
最初为 120k RU 创建容器时,每个物理分区最终将有 12 PP - 10k RU 限制。一旦开始加载数据,最终可能会产生更多 PP。以下情况可能会导致“ split ”:
- LP 大小(每个分区键的数据总大小)大于 20GB
- PP 的大小(该 PP 中存储的所有 LP 大小的总和)大于 50GB
A physical partition split simply creates a new mapping of logical partitions to physical partitions.
根据 PP 存储分配,您似乎进行了多次“拆分”,导致配置了约 20 个 PP。 每次发生“拆分”时,Cosmos DB 都会创建两个新的 PP,并在新创建的之间平均拆分现有 PP。一旦这个过程完成,“倾斜的”PP 就会被删除。您可以通过您提供的指标图表上的 PP id 粗略地猜测拆分数量(如果没有发生拆分,您将获得 id:[1-12])。
由于请求扇出和跨分区查询,拆分可能会导致更高的 RU 消耗。
关于azure-cosmosdb - 同一查询的 Cosmos DB 图 RU 成本不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66539677/