我们需要以与查询参数相同的顺序创建复合索引。这个顺序对性能有影响吗?
想象一下,我们有一个地球上所有人类的集合,其中有一个关于 sex
的索引(99.9% 的时间是“男性”或“女性”,但仍然是字符串(不是二进制))和一个索引关于名称
。
如果我们希望能够选择具有特定 name
的特定 sex
的所有人,例如所有名为 “John” 的“男性”,最好先使用 sex
还是先使用 name
的复合索引?为什么(不)?
最佳答案
雷德桑德罗,
你必须考虑 Index Cardinality
和 Selectivity
。
1。索引基数
索引基数是指一个字段有多少个可能的值。 sex
字段只有两个可能的值。它具有非常低基数。 姓名、用户名、电话号码、电子邮件
等其他字段对于集合中的每个文档都将具有更独特的值,这被认为是高基数。
更大的基数
字段的基数越大,索引就越有用,因为索引缩小了搜索空间,使其成为一个更小的集合。
如果您有关于
sex
的索引,并且您正在寻找名叫 John 的男性。如果您首先按sex
进行索引,您只会将结果空间缩小大约 %50。相反,如果您按name
进行索引,您会立即将结果集缩小到一小部分名为 John 的用户,然后您将引用这些文档来检查性别。经验法则
尝试在
high-cardinality
键上创建索引,或者将high-cardinality
键放在复合索引的首位。您可以在本书的复合索引部分了解更多信息:
2。选择性
另外,您想使用索引 selectively并编写查询以限制具有索引字段的可能文档的数量。为简单起见,请考虑以下集合。如果你的索引是 {name:1}
,如果你运行查询 { name: "John", sex: "male"}
。您必须扫描 1
文件。因为您允许 MongoDB 具有选择性。
{_id:ObjectId(),name:"John",sex:"male"}
{_id:ObjectId(),name:"Rich",sex:"male"}
{_id:ObjectId(),name:"Mose",sex:"male"}
{_id:ObjectId(),name:"Sami",sex:"male"}
{_id:ObjectId(),name:"Cari",sex:"female"}
{_id:ObjectId(),name:"Mary",sex:"female"}
考虑以下集合。如果你的索引是 {sex:1}
,如果你运行查询 {sex: "male", name: "John"}
。您必须扫描 4
个文档。
{_id:ObjectId(),name:"John",sex:"male"}
{_id:ObjectId(),name:"Rich",sex:"male"}
{_id:ObjectId(),name:"Mose",sex:"male"}
{_id:ObjectId(),name:"Sami",sex:"male"}
{_id:ObjectId(),name:"Cari",sex:"female"}
{_id:ObjectId(),name:"Mary",sex:"female"}
想象一下更大数据集上可能存在的差异。
复合索引的一点解释
很容易对复合索引做出错误的假设。根据MongoDB docs on Compound Indexes .
MongoDB supports compound indexes, where a single index structure holds references to multiple fields within a collection’s documents. The following diagram illustrates an example of a compound index on two fields:
当您创建复合索引时,1 个索引 将包含多个字段。因此,如果我们通过 {"sex": 1, "name": 1}
对集合进行索引,则索引大致如下:
["male","Rick"] -> 0x0c965148
["male","John"] -> 0x0c965149
["male","Sean"] -> 0x0cdf7859
["male","Bro"] ->> 0x0cdf7859
...
["female","Kate"] -> 0x0c965134
["female","Katy"] -> 0x0c965126
["female","Naji"] -> 0x0c965183
["female","Joan"] -> 0x0c965191
["female","Sara"] -> 0x0c965103
如果我们通过 {"name": 1, "sex": 1}
对集合进行索引,则索引大致如下:
["John","male"] -> 0x0c965148
["John","female"] -> 0x0c965149
["John","male"] -> 0x0cdf7859
["Rick","male"] -> 0x0cdf7859
...
["Kate","female"] -> 0x0c965134
["Katy","female"] -> 0x0c965126
["Naji","female"] -> 0x0c965183
["Joan","female"] -> 0x0c965191
["Sara","female"] -> 0x0c965103
将 {name:1}
作为 Prefix在使用复合索引时会更好地为您服务。关于这个主题还有更多可以阅读的内容,我希望这可以提供一些清晰的信息。
关于mongodb - 复合索引的顺序在 MongoDB 性能方面有何影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33545339/