今天群里有个小伙伴问了个问题。

对某个字段 sort 后,再 skip 一个超大值,之后 MongoDB 会报错,因为用于排序的内存超过了 32m。如果 skip 一个小值,就不会报错。

问题是,这个排序字段是没有索引的,那么 sort 时数据都是放在内存里面 sort。为啥 skip 小就没事,skip 大就会撑爆内存呢?

小伙伴说,已经问了 10 个群了,没人回答为啥。


嗯?

skip 一个超大值,然后占用很多内存报错,这不是显而易见的吗。

几乎每本数据库的书都会提到,不要 skip 一个超大值,会产生性能问题,然后给出几个替代方案。

仔细一想,有古怪。由于没有索引,数据拿到内存里面进行排序,二手手机号码买卖那 skip 多和少应该没有影响。但是事实上,skip 超大值的确会导致内存超出限制。

Google 了半天,全是怎么处理这个问题,没有提到为什么产生这个现象。

经过谨慎的思(nao)考(bu),我提出了一个想法:

问题的根源显然出现在 MongoDB 的排序算法上,但是本人未能找到其算法实现如果我来实现排序算法,我会将所有数据全部读取后,再进行排序吗?NO在一个存在 limit、skip 的查询语句中,数据库排序后需要临时保存的数据量是 limit + skip 条数据。那数据库的排序操作,很可能是先获取 limit+skip 条数据作为一个 chunk,排序后,开始逐一获取剩余数据。之后每条新数据与 chunk 内数据进行比较,符合要求则进入,并踢出 chunk 内对应数据。所以,当 skip 超大时,chunk 的数据量也超大,最后超过了 32m 从而报错。

以上想法能够解释问题现象,但是没有文档依据。

好吧,那我们去看看官方文档:

Add an index, or specify a smaller limit
In MongoDB, sort operations can obtain the sort order by retrieving documents based on the ordering in an index. If the query planner cannot obtain the sort order from an index, it will sort the results in memory. Sort operations that use an index often have better performance than those that do not use an index. In addition, sort operations that do not use an index will abort when they use 32 megabytes of memory.
翻译过来说,就是在mongodb中,sort操作能通过索引获得在要排序的documents中的顺序,如果执行计划中没有从索引中获取顺序,它就会在内存中对检索结果进行排序。 使用索引的Sort操作在性能上往往比没有使用索引的sort要好。另外。没有使用索引的sort操作在使用了32M内存的时候会被终止掉(使用内存排序时,限制查询结果默认最多为32M,超过的话查询则会被终止)。关于mongoDB使用sort排序引发的生产bug

对问题的建议是添加索引,或者减少 limit,描述中限制查询结果最多为 32m。

以上文档能在一定程度上佐证我的想法。


更多相关文章

  1. Linux内核发送构造数据包的方式
  2. udp数据报从网卡驱动到用户空间流程总结
  3. 数据库集群和分布式数据库的区别
  4. Elasticsearch—用logstash增量导入Mysql数据
  5. MongoDB-Elasticsearch 实时数据导入
  6. 网络子系统在链路层的收发过程剖析
  7. ‘大案牍术’遇上阿里云数据库POLARDB,火花四起
  8. OceanBase、X-DB、POLARDB 分布式关系型数据库,各自的优势是什么?
  9. spark与kafka集成

随机推荐

  1. Android帧布局-实现渐变效果
  2. 搭建Android开发环境01——Java
  3. Android自定义ProgressBar
  4. 查看android路由表
  5. Android修改PackageInstaller自动安装指
  6. Android SDK更新失败对策
  7. 一张图片覆盖在另一个图片上
  8. android:broadcast_01
  9. android检查sd卡是否可写
  10. Tab游标,实现fragment滑动,,游标改变