在CosmosDB中索引数组

Bow*_*opa 7 azure azure-cosmosdb

为什么CosmosDB默认不进行索引?默认索引路径是

"path": "/*"
Run Code Online (Sandbox Code Playgroud)

这不是指"索引一切"吗?不是"除了数组之外的所有索引".

如果我将我的数组字段添加到索引中,如下所示:

"path": "/tags/[]/?"
Run Code Online (Sandbox Code Playgroud)

它将工作并开始索引特定的数组字段.

但我的问题是为什么不"索引一切"索引一切?

编辑:这是一篇描述我所看到的行为的博客文章.http://www.devwithadam.com/2017/08/querying-for-items-in-array-in-cosmosdb.html Array_Contains查询非常慢,显然没有使用索引.如果您明确地将相关字段添加到索引中,那么查询很快(显然它们开始使用索引).

Mar*_*ith 8

"新"索引布局

索引类型中所述

Azure Cosmos容器支持不再使用哈希索引类型的新索引布局.如果在索引策略上指定哈希索引类型,则容器上的CRUD请求将静默忽略索引类型,并且容器的响应仅包含Range索引类型.默认情况下,所有新的Cosmos容器都使用新的索引布局.

下面的问题并不能适用于新的索引布局.默认索引编制策略工作正常(并传递结果36.55 RUs).但是,预先存在的集合可能仍在使用旧布局.

"旧"索引布局

我能够重现ARRAY_CONTAINS您所询问的问题.

使用来自SO数据转储的100,000个帖子设置CosmosDB集合(例如,此问题将表示如下)

{
    "id": "50614926",
    "title": "Indexing arrays in CosmosDB",
     /*Other irrelevant properties omitted */
    "tags": [
        "azure",
        "azure-cosmosdb"
    ]
}
Run Code Online (Sandbox Code Playgroud)

然后执行以下查询

SELECT COUNT(1)
FROM t IN c.tags
WHERE t = 'sql-server'
Run Code Online (Sandbox Code Playgroud)

该查询使用默认索引策略获取了2,000多个RU,并且添加了以下93个(如链接文章中所示)

{
    "path": "/tags/[]/?",
    "indexes": [
        {
            "kind": "Hash",
            "dataType": "String",
            "precision": -1
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

但是,您在此处看到的并不是默认情况下未对数组值进行索引.只是默认范围索引对您的查询没有用.

范围索引使用基于部分前向路径的键.因此将包含如下路径.

  • tags/0/azure
  • tags/0/c#
  • tags/0/oracle
  • tags/0/sql-server
  • tags/1/azure-cosmosdb
  • tags/1/c#
  • tags/1/sql-server

使用此索引结构,它从,tags/0/sql-server然后读取所有剩余tags/0/条目和整个条目,tags/n/其中where n是大于的整数0.需要检索和评估映射到这些中的任何一个的每个不同文档.

相比之下,哈希索引使用反向路径(更多细节 - PDF)

StackOverflow理论上允许UI添加每个问题最多5个标签,因此在这种情况下(忽略一些问题通过站点管理活动有更多标签的事实),感兴趣的反向路径是

  • sql-server/0/tags
  • sql-server/1/tags
  • sql-server/2/tags
  • sql-server/3/tags
  • sql-server/4/tags

使用反向路径结构查找具有值sql-server的叶节点的所有路径是直截了当的.

在该特定用例中,由于阵列被限制为最多5个可能的值,因此还可以通过仅查看那些特定路径来有效地使用原始范围索引.

以下查询在我的测试集合中使用了具有默认索引策略的97个RU.

SELECT COUNT(1)
FROM c
WHERE  'sql-server' IN (c.tags[0], c.tags[1], c.tags[2], c.tags[3], c.tags[4])
Run Code Online (Sandbox Code Playgroud)