为什么mongodb无法有效地对复合索引的非前缀子索引进行排序?
例如,如果您在集合上为{ a: 1, b: 1, c: 1 }
编制索引,则可以使用{ a: 1, b: 1 }
或{ a: 1 }
进行排序,这些被称为前缀
find().sort({ a: 1 }).limit(10)
如果我们将相等条件放在“ a”键上,同样的方法,我们可以对“ b”键进行排序而没有问题
find({ a:'example' }).sort({ b: 1 }).limit(10)
通常,如果我们设置属于一个有限集的条件(属于元素列表),我们将能够检索属于该列表的每个键,然后对选定的键执行SORT_MERGE文件限制,因为每个键“ a”使我们可以访问“ b”键的有序索引 因此这些查询通常会使用索引完成
find({ a: { $in: ['exa','ample','test'] }).sort({ b: 1 }).limit(10)
但另一方面,如果我尝试这样的请求:
find().sort({ b: 1 }).limit(10)
他将进行一次COLSCAN(将遍历所有文档),然后对所有数据进行排序,最后取最后10个。
索引{ a: 1, b: 1, c: 1, c: 1 }
的使用效率更高。
我们可以扫描索引为“ a”的键,然后对请求的限制执行SORT_MERGE。
最后,它使我们成为O(键+限制)算法,其中键是不同的“ a”键的数量,并限制了我们要检索的文档数量。它为我们节省了COLSCAN,并且使我们免于对收集的数据进行排序。
合理地假设与文档相比,不同的“ a”键要少一些,因为不应使用复合索引。不同的“ a”键越少,应该感觉到的性能提升就更多。
在这里我只提到了在第一个索引上没有任何条件的情况,但是如果我们添加这样的条件
find({ { a: { $gt: 100 } }).sort({ b: 1 }).limit(10)
find({ a: /^spa/i }).sort({ b: 1 }).limit(10)
我们可以想象完全相同的操作,只是我们限制了要扫描的“ a”键的数量。
对于某些请求,我们甚至可以在某些情况下获得疯狂的性能,甚至在没有一些子索引的情况下也可以做到
我在哪里错了?