我目前正在扩展现有系统,需要对包含约 300 万个文档的容器“Parts”进行新查询。我使用以下查询来查找所有文档,其中包含“parts”数组中的项目,partNumber为“ABC12345”:
// 69 RUs small test
SELECT c.partNumber
FROM c
WHERE ARRAY_CONTAINS(c.parts, { 'partNumber': 'ABC12345'}, true)
这个查询非常慢。对于某些参数,这将需要几秒钟,占用约 100 RU,但对于更频繁发生的匹配,这将花费更长的时间,并占用数千 RU。这是个问题。此测试是使用 Azure 门户完成的(如果有影响的话)。
我首先尝试优化查询,但这并没有提高性能。我一直在研究这个问题,与我对 CosmosDB 的最初理解相反,数组默认情况下没有索引。因此,我在属性partNumber中添加了一个索引,希望能够优化性能,如下:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
},
{
"path": "/parts/[]/partNumber/?"
}
],
"excludedPaths": [
{
"path": "/\"_etag\"/?"
}
]
}
但是,我没有看到性能有任何改进。如何验证索引是否正确定义;有没有办法“浏览”CosmosDB 索引,以便我可以确保我已正确设置并正确使用索引?
在开始寻求替代解决方案之前,我想首先验证这一点。
零件数组上的值字段partNumber应该已经被索引,因为所有字段都被索引,除非您特别排除它们。
我认为您的实际问题是使用 ARRAY_CONTAINS 并将 true 作为最后一个参数传递(partial_match)。根据我的经验,无论索引如何,这往往会导致完整的集合扫描。当部分匹配为 true 时,它在逻辑上相当于 string CONTAINS 等函数,但与索引不能很好地配合。
我相信您可以使用联接和相等子句来表达查询,而不是 ARRAY_CONTAINS,这应该命中索引。
SELECT
c.partNumber
FROM
c
JOIN
p IN c.parts
WHERE
p.partNumber = 'ABC12345'