我有一个场景,我需要根据azure cosmos db中的id属性检索单个文档。唯一的问题是我不知道分区密钥,因此无法使用文档URI来访问它。
根据我的理解编写一个简单的查询,如
SELECT * from c WHERE c.id = "id here"
应该是可行的方法,但我遇到了此查询的严重性能问题。大多数查询需要30到60秒才能完成,并且似乎消耗了大量的RU / s。执行10个并发查询时,每个分区的最大RU / s高达30.000。 (每个分区配置10.00)导致限制甚至更慢的响应。
该集合包含10个分区,每个分区大约3 Mb,总共30 Mb和大约1,00,000个文档。我的索引政策如下所示:
{
"indexingMode": "lazy",
"automatic": true,
"includedPaths": [
{
"path": "/*",
"indexes": [
{
"kind": "Range",
"dataType": "Number",
"precision": -1
},
{
"kind": "Hash",
"dataType": "String",
"precision": 3
}
]
}
],
"excludedPaths": []
}
并且一致性设置为EVENTUAL
,因为我并不真正关心读/写顺序。该集合受到一些写入压力,每分钟大约30次写入,每个文档的TTL为1年,但这似乎不会对RU产生可测量的影响。我只在查询文档时遇到这种问题。
是否有人遇到类似问题并且可以提供修复/缓解措施?我的查询或索引策略有问题吗?我不知道为什么我的查询消耗了那么多资源。
答案 0 :(得分:5)
我甚至遇到了类似的问题。我的数据库是16 GB,有2个分区,每个分区有10,000 RU。
通过收集查询指标,我发现query by id
可能正在进行表扫描,而不是从索引中查找。
以下是按ID的查询指标:
SELECT * FROM c where c.id = 'id-here'
--Read 1 record in 1497.00 ms, 339173.109 RU
--QueryPreparationTime(ms): CompileTime = 2, LogicalBuildTime = 0,
PhysicalPlanBuildTime = 0, OptimizationTime = 0
--QueryEngineTime(ms): DocumentLoadTime = 1126, IndexLookupTime = 0,
RuntimeExecutionTimes = 356, WriteOutputTime = 0
请注意主要花费在DocumentLoadTime
和IndexLookupTime = 0
上的时间。
虽然索引字段的查询非常快。
SELECT * FROM c WHERE c.indexedField = 'value'
--Read 4 records in 2.00 ms, 7.56 RU
--QueryPreparationTime(ms): CompileTime = 0, LogicalBuildTime = 0,
PhysicalPlanBuildTime = 0, OptimizationTime = 0
--QueryEngineTime(ms): DocumentLoadTime = 0, IndexLookupTime = 1,
RuntimeExecutionTimes = 0, WriteOutputTime = 0
与id的查询形成对比,在使用索引时不会消耗DocumentLoadTime
,IndexLookupTime
为1毫秒。
问题是id
应该是主键,默认情况下应该编入索引,但看起来不是。你甚至无法为它添加自定义索引策略。
我目前正在记录微软支持的门票并等待澄清。
<强>更新强>
微软的支持得到了回复,他们已经解决了这个问题。他们为集合添加了IndexVersion 2
。不幸的是,门户网站尚未提供它,新创建的帐户/集合仍未使用新版本。您必须与Microsoft支持部门联系以更改您的帐户。
以下是索引版本为2的集合的新结果,并且有了很大的改进。
SELECT * FROM c where c.id = 'uniqueValue'
-- Index Version 1: Request Charge: 344,940.79 RUs
-- Index Version 2: Request Charge: 3.31 RUs
SELECT * FROM c WHERE c.indexedField = 'value' AND c.id = 'uniqueValue'
-- Index Version 1: Request Charge: 150,666.22 RUs
-- Index Version 2: Request Charge: 5.65 RUs
答案 1 :(得分:4)
我的测试数据库大约有300k记录 当我尝试选择ID时,只有这样
SELECT * FROM c where c.id = 'xxx'
我花了很多时间和RU
但是当我尝试使用分区键时
SELECT * FROM c where c.id = 'xxx' AND c.partitionField = 'yyy'
它非常快
所以我认为你必须重新构建你的数据库,并考虑制作分区的哪个字段
答案 2 :(得分:0)
Cosmos的密钥是重新考虑分区密钥。 我不知道您在使用什么,但是请使其非常可用。
最近,我一直在向所有文档添加“表格”属性,但是您可以非常轻松地将表格名称用作分区键!真的就像是在CosmosDB集合的布丁中漂浮了一堆SQL表一样。