MongoDB 开发人员提示和技巧中的提示#25是否正确?
它说这个查询:
collection.find({"x" : criteria, "y" : criteria, "z" : criteria})
可以优化
collection.ensureIndex({"y" : 1, "z" : 1, "x" : 1})
我认为这是错误的,因为要使它起作用, x 应该在前面。我认为索引的顺序很重要。
那么我哪里做错了?
MongoDB 开发人员提示和技巧中的提示#25是否正确?
它说这个查询:
collection.find({"x" : criteria, "y" : criteria, "z" : criteria})
可以优化
collection.ensureIndex({"y" : 1, "z" : 1, "x" : 1})
我认为这是错误的,因为要使它起作用, x 应该在前面。我认为索引的顺序很重要。
那么我哪里做错了?
Model.createIndex({ a: 1, b: 1, c: 1, d: 1 });
我将其想象为:
该链形成一个树结构,因此被选择存储在B-TREE data structure
.
在这种情况下,我很想将此存储系统称为 a compound-index-chain
。
通常我们建立索引来执行两种类型的操作1. Query Operation like find()
和2. Non-query operation like Sort()
现在您在{ a: 1, b: 1, c: 1, d: 1 }
. 但仅创建索引是不够的。如果您不以使用这些索引的方式构建数据库操作(查找和排序),它就会变得低效甚至无用。
让我们深入挖掘一下什么样的查询支持什么样的索引?
寻找():
prefixes
复合索引还支持find()
对字段的索引查询操作{a:1},
{a:1, b:1},
{a:1, b:1, c:1}
// Index prefixes are the beginning subsets of indexed fields
@JohnnyHK 已经说过“查找查询对象中字段的顺序不相关。”
performance
即使 find() 查询使用相同的索引并且正在使用索引,如果 find() 中的字段顺序与其他后续字段相比不具有高度选择性,则查询的结果将不一样(可能会降级) 。find({a: 'red', b: tshrt})
has ,那么即使两个查询都使用一个 index HIGH SELECTIVITY
,查询的效率也会低于find({a: 'tshirt', b: 'red'})
这个查询 hs 。LOWER SELECTIVITY
{a:1, b:1}
Query selectivity
是指查询谓词排除或过滤出集合中的文档的程度。查询选择性可以决定查询是否可以有效地使用索引,甚至可以完全使用索引。现在让我们来看看复合索引的前缀
注意:find()
复合索引 {a:1, b:1, c:1, d1} 的这个 {a:1, c:1} 前缀的行为与其其他前缀不同吗?
在这种情况下,find()
操作将无法有效地利用我们的复合索引。
发生的事情是a:1 field
索引将只能支持查找查询。index onc:1 field
根本不会被使用,因为由于前缀compound-index-chain
中没有,所以在两者之间被打破了。b:1 index field
因此,如果 find() 查询同时对 a 和 c 字段进行操作,则将field a:1
使用 IXSCAN(即在 a 上使用索引)和field c
COLLSCAN(即不使用索引)。意味着查询将比使用单独的复合索引要慢,{a:1,c:1}
但比根本没有任何索引要快。
结论是索引字段是按顺序解析的;如果查询省略了特定的索引前缀,则无法使用该前缀后面的任何索引字段。
2.排序():
对于non-query-operation(i.e Sort)
,在创建复合索引时,复合索引的子集必须相同order of the index
,也必须位于same or oposite direction
为每个字段指定的方向之一。
让我们看看{ a: 1, b: 1, c: 1, d: 1 }
带有升序方向的复合索引在 sort() 操作中的表现:
让我们看一下索引字段在排序中的方向。
{a:1, b:1, c:1, d:1} // in same-direction as of our compound index
{a:-1, b:-1, c:-1, d:-1 } // in reverse-direction of our compound index
// But these field have neither same-direction nor reverse-direction but is ARBITARY/MIXED. Thus
// Index will be discarded while performing sorting with these fields and directions
{a:-1:, b:1, c:1, d:1}
compound index on {a:1, b:-1}
可以支持在 {a:1,b:-1} (same-direction) 和 {a:-1,b:1}(reverse-direction) BUT 上的索引排序NOT support {a:-1, b:-1}
。现在让我们看看索引字段在排序中的顺序
最佳排序:
// compound index
{a:1, b:1, c:1, d:1}
// prefix of the compound index
{a:1},
{a:1, b:1},
{a:1, b:1, c:1}
复合指数链断裂:
当一个排序操作被复合索引部分覆盖时,可能需要检查内存中的非索引匹配结果集。
Model.find({ a: 2 }).sort({ c: 1 }); // will not use index for sorting using field c. But will be used for finding
Model.find({ a: { $gt: 2 } }).sort({ c: 1 }); // will not use index for sorting But will be used for finding
// because compound-index-chain-break due to absence of field b of the prefix {a:1, b:1, c:1} of our compound index {a:1, b:1, c:1, d:1}
按非前缀子集排序:
当索引的前缀键同时出现在查询谓词(即 find())和 sort() 中时,位于排序子集之前(或重叠)的索引字段必须具有相等条件($eq,$gte,$lte ) 在查询中。所以
复合索引也可以支持对其索引前缀的索引查询。
Model.find({ c: 5 }).sort({ c: 1 }); // will not use index at all because it does not belongs to any of the prefix of our compound index
Model.find({ b: 3, a: 4 }).sort({ c: 1 }); // will use the index for both finding and sorting as it belongs to one our index prexfix ie. {a:1, b:1, c:1}
Model.find({ a: 4 }).sort({ a: 1, b: 1 }); // will use index for finding but not use index for sorting because a field is overlapped.
Model.find({ a: { $gt: 4 } }).sort({ a: 1, b: 1 }); // will use index for both finding and sorting because overlapped field (a) in the predicate uses equality operator and it belongs to the prefix {a:1, b:1}
Model.find({ a: 5, b: 3 }).sort({ b: 1 }); // will not use index for sorting
Model.find({ a: 5, b: { $lt: 3 } }).sort({ b: 1 }); // will use index for both finding and sorting
希望这可以帮助某人