是否可以物理重组mongoDB集合以避免使用sort()?

时间:2013-08-01 16:04:52

标签: mongodb optimization

我有一个存储文章信息的集合。该集合用于存档目的,因此它是只读的。目前只使用了两个字段:“title”和“page_length”。因为我总是对首先获得更长的文章感兴趣,所以我有以下索引:{title:1,page_length:-1}。

我发现排序仍然很慢,因为集合非常大而且不适合内存。

假设我在这个集合上使用的几乎每个查询都需要排序({page_length:-1}),有没有办法简单地按照page_length的顺序将记录存储在磁盘上?换句话说,是否有一种简单的方法可以使集合中的第一条记录成为最大的page_length值,第二条记录是第二条记录,依此类推?

这样我就可以使用limit(n)获取前n个记录而无需运行排序。有什么想法吗?


使用更多信息进行更新:

我将其用于搜索自动完成功能,因此速度至关重要。我一直在使用的查询如下所示:

db.articles.find({"title": /^SomeKeyword/}).sort({page_length:-1})

我很高兴创建多个索引,因为插入不是问题,我只想最大化读取速度。

编辑:作为参考,我实际上能够通过将find()。forEach()用于新集合来重新组织集合中的记录。然后我搜索了该集合并抓住了前N个结果,而不需要任何排序,这非常有效。请注意,这只能起作用,因为我的数据集不会改变。

2 个答案:

答案 0 :(得分:1)

您的索引{ title: 1, page_length: -1 }不会用于如下所示的查询:

db.collection.find( {} ).sort( { page_length: -1 } );

MongoDB只能使用从左到右的复合索引,因此为了使用索引,你需要拥有" title"作为查找或排序参数:

db.collection.find({title:' foo'})。sort({page_length:-1});    db.collection.find()。sort({title:1,page_length:-1});

解释会告诉你:

db.so.find( {} ).sort( { page_length: -1 } ).explain();

{
    "cursor" : "BasicCursor",
    …

如果您将索引更改为:

db.so.ensureIndex({ page_length: -1, title: 1 } );

然后索引将用于排序,但您不能使用索引只是通过title进行查找,您将需要一个额外的索引。如果您真的只对这两个字段感兴趣并确保使用覆盖索引有帮助。您必须使用{ page_length: -1, title: 1 }获得复合索引,并且可以确保使用投影来使用它:

db.collection.find({},{page_length:1,title:1,_id:0})。sort({page_length:-1});

但是你不能决定或影响MongoDB如何在磁盘上存储东西。

答案 1 :(得分:0)

我可以想到一个使用两个查询的解决方案。

首先,您可以执行covered query来获取您关注的文档列表。其次,您可以使用检索到的文档列表和$in运算符来获得最终结果。

覆盖的查询将在内存中运行(或者至少在磁盘上顺序运行),因此它应该很快,$in可以使用_id索引,并且应该具有合理的数量文件。