这有什么意义吗?因为前缀的每个值只包含任何后缀的一个值,所以在前缀之后就没有进一步的排序了。
可以吗?确定。应该是吗?我有点(但不是完全)不同意@Joe的观点,并说"可能不会"。
对于这个答案,我们将使用A
表示唯一字段,B
表示考虑的任何后续字段。
在索引中包含额外键的两个更常见的原因是:
- 进一步减少数据库在执行查询时必须执行的多余扫描量。
- 满足查询形状中请求的排序。
正如您在问题中注意到的,这里的第二个动机并不适用。如果没有复合索引并且请求的查询包含{ A: 1, B: 1 }
上的排序,那么数据库将最终执行手动排序,这可以很容易地解决。将来可能会对数据库进行优化,以考虑到这些知识,但据我所知,目前还没有。无论如何,逻辑上我们知道由于A
的唯一性,B
不会影响结果的排序,因此这个问题可以"解决"。通过让应用程序在{ A: 1 }
上指定更简单(但逻辑上仍然相同)的排序。
前一种考虑稍微有趣一些。假设A
的唯一性被数据库强制执行,我们知道两件事:
- 存在
{ A: 1 }
的单个字段索引,该索引已经符合A
上过滤的查询的使用条件。 - 对于查询谓词中提供的每个
A
值,现有的单个字段索引将最多扫描一个不会返回给客户端的额外文档。这是因为A
的每个值最多只有1个匹配文档,但该文档无法匹配基于B
值的完整查询谓词。
这导致了一个有趣的考虑点。如果B
谓词是高度选择性的,那么额外的复合索引可以帮助避免一些文档扫描。同样,对于每个A
的值,最多只能进行1次额外的文档扫描。但是这样做的代价是维护一个完全独立的索引,如果没有单个字段索引的唯一性约束,这个索引将是冗余的。在大多数情况下,我怀疑这种权衡是否值得。
如果你在应用层强制A
的唯一性,而相关的单字段索引不存在,那么创建复合索引变得更有吸引力。
@Joe也提到了我想到的一个特殊的例外。如果您只向客户端返回A
和B
字段,那么复合索引还具有覆盖查询的优势。在这种情况下,您将始终能够避免在执行查询时获取和扫描文档,这可能使维护该索引更有吸引力。
通常情况下,这里没有明确的答案。在大多数情况下,我个人会选择不使用复合索引,但当然也有例外。
是的,唯一字段可以是索引中列出的第一个字段。
索引将仅用于在该唯一字段上包含过滤条件或按该唯一字段排序的查询。这样的索引对于创建覆盖查询也很有用,这些查询从其他索引字段之一返回数据。