MongoDB sort, limit. skip

在MongoDB中,当我们在find语句上同事使用sort、skip、limit时,不管他们的顺序怎么样,总是先执行sort,再执行skip,然后执行limit。如下语句:

db.foo.find({}).skip(2).limit(10).sort({age: -1})

数据库会先对所有记录按照age倒序排序,然后在跳过2个记录,然后返回10个记录。MongoDB记录进行排序的时候,是把所有符合find({})中指定的记录都读取到内存,然后进行排序。如果读取的所有符合find({})的记录超过了限制(一般默认32M),那么就MongoDB就会给这条语句报错、返回,log信息大致如下:Query failed with error code 96 and error message 'Executor error during find command :: caused by :: errmsg: "Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit."' on server 10.1.1.155:27017; nested exception is com.mongodb.MongoQueryException: Query failed with error code 96 and error message 'Executor error during find command :: caused by :: errmsg: "Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit."'  可以通过两种方法来解决。一、增加增加排序的内存,重新分配更大的排序内存(320M):

db.test({setParameter:1, internalQueryExecMaxBlockingSortBytes:335544320})

二、另一种就是对排序的字段创建索引:

db.getCollection("foo").createIndex({"age":-1})

很容易就可以知道,第一种不是很好的解决方案。这就要求我们在开发初期就在创建索引上下好功夫,免得日后麻烦。

 

 在shell上为集合创建索引语句原型如下:

db.collection.createIndex(keysoptions)

例如: db.foo.createIndex({age:-1}, {background: true, unique:true})

这里有如下几点需要说明一下:

1)、options有 

background ->  true:后台创建index,这样系统就不会阻塞对其他数据库的操作;默认是false。一般设置为true

unique  -> true: 这样可以让一个文档中只有一个Index key,如上面的只有一个age。文档中已经有了age,随后的insert,或者update中再插入一个age的话,就会报错。当然是同一级文档下。如果内嵌文档中再包含一个age不会报错。默认是false,经常要设置成true

sparse - > true: 创建稀疏Index,对应不包含age的文档,不会把它记录在Index中,这样在查找的时候就会跳过不包含age的文档。默认是false, 对于没有这个key的文档,也会在index B-tree中创建索引,按照值时nil来排序。

expireAfterSeconds -> 超时index,超过一定秒数,就会删掉相应的index key,并且也 删掉文档。

 

2)当我们为Age创建了倒序的索引之后,后面我们再执行

db.foo.find({}).skip(2).limit(10).sort({age: -1})

语句时,将直接根据已经排序的Index跳过2个记录,返回10个,不再需要把所有数据导入内存进行排序后返回。

 

注意:索引也需要耗些内存的,另外如果一个集合创建了太多的索引,在写入的时候,每一个索引都要去update它们的结构体,这样会耗费时间。所以,如果你的数据写入大于读取操作很多的话建议少建些索引,需要自己根据业务需要来作个权衡。

重复创建相同数据库会返回失败。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值