Azure Cosmosdb(Documentdb)默认索引策略不适用于StartsWith()函数

时间:2018-01-30 12:24:05

标签: azure indexing azure-cosmosdb

运行查询时遇到以下异常

SELECT TOP 10 c.name
FROM Customer c
WHERE STARTSWITH(c.name, 'Bob')

异常:

An invalid query has been specified with filters against path(s) that are not range-indexed. Consider adding allow scan header in the request.

我通过将索引更改为

来解决了这个问题
{
    "path": "/",
    "indexes": [
        {
            "kind": "Range",
            "dataType": "Number",
            "precision": -1
        },
        {
            "kind": "Hash",
            "dataType": "String",
            "precision": 3
        }
    ]
},
{
    "path": "/name/?",
    "indexes": [
        {
            "kind": "Range",
            "dataType": "String",
            "precision": -1
        }
    ]
}

但我有两个问题:

  1. 为什么没有默认的索引工作?不应该"path": "/*"索引所有内容吗?
  2. 为什么必须添加"path": "/"?你为什么需要它?
  3. P.S。我已经阅读了how-to guide上的索引政策部分,但仍然没有理解它。任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:1)

为什么没有默认索引工作?不应该"路径":" / *"索引一切?

确实如此,但重要的是如何。

默认索引不起作用,因为对于数据类型String,它创建为hash索引。散列意味着索引不存储实际值,而是由某些hash function生成的通常较小的乱码(散列)值。要获得匹配,您需要与产生相同哈希值的值进行比较。假设合理长度的高质量散列函数,它将需要相同的原始值。因此,c.name = "Bob"将涵盖该索引。

The documentation也确认说:

  

索引类型   Hash支持高效的相等和JOIN查询。

您的查询谓词STARTSWITH(c.name, 'Bob')正在对c.name属性执行功能检查。 Startswith()没有好的方法来生成所有可能的匹配哈希值以进行比较而不扫描所有文档。 因此,正如错误所述:您对给定属性的索引无法提供此查询。

为什么必须添加"路径":" /"?你为什么需要它?

我不确定是否/为什么它在技术上是强制性的(与应用一些隐式默认值相比),但我认为合理的要求是让用户明确地盯着默认值并批准或修改它们

设计比例 - 永远不要进行全面扫描。 另一方面,设计用于处理集合的关系SQL数据库用于无模式非结构化数据,针对单个文档进行了优化,并且是为了扩展而设计的。您永远不应该进行全面扫描并阅读所有文档,因为它无法扩展。因此,您应该设计和规划查询数据的方式。

默认值几乎不会是最优的。 正如您所经历的那样,每个索引都有不同的目标 - 范围索引支持排序,但哈希索引更紧凑,使用更快。同样合适的索引精度取决于您的数据,值分布和应用程序需求。

成本影响。 此外,每个索引在每次插入/更新/删除时都有存储成本和额外工作量(RU)以保持同步。因此,您的索引选择会影响性能和帐单。你可能都在乎两者。

答案 1 :(得分:0)

在玩了一会儿之后,我想我可能已经找到了问题的答案。

默认"path": "/*"不起作用的原因是因为范围索引的dataType设置为Number而name的值显然是字符串。这就是我需要为name添加额外范围索引的原因。

我还注意到"path": "/*""path": "/"会产生相同的结果。我想它们是可以互换的。