美文网首页
Mongo排序超出最大内存错误

Mongo排序超出最大内存错误

作者: AC编程 | 来源:发表于2023-01-30 13:34 被阅读0次

一、背景

MongoDB是一个文档数据库,这意味着它将数据存储在类似JSON的文档中。我们认为,这是考虑数据的最自然方法,比传统的行/列模型更具表现力和功能。

二、现象

排序、分页功能也是在使用过程中最常见的查询,最近Spring data mongo使用排序、分页功能查询数据量在5000w左右的数据时出现超出最大内存限制错误。

代码分析

Page<VmMessageDtlVO> data = new Page<>();
// add common condition
Criteria criteria = commonCond(vmMessageDtlDTO);
Query query = new Query(criteria);
// order by createTime desc
query.with(Sort.by(Sort.Direction.DESC, "createTime")).skip(vmMessageDtlDTO.getCurrentPageIndex()).limit(vmMessageDtlDTO.getPageSize());
List<VmMessageDtlModel> list = mongoTemplate.find(query, VmMessageDtlModel.class);
// format data info
List<VmMessageDtlVO> result = convertList(list);
Long rows = mongoTemplate.count(query, VmMessageDtlModel.class);

使用Spring Query直接先排序后分页,如果根据条件匹配后仍然有海量数据的话就需要对大批量数据进行排序操作,不使用磁盘缓存的话很容易就出现内存暴增的情况,也是程序运营中的忌讳,如果多个查询同时进行则有可能程序直接内存爆掉。

三、错误信息

Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation

org.springframework.data.mongodb.UncategorizedMongoDbException: Query failed with error code 292 and error message 'Executor error during find command :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in.' on server 192.168.1.198:30014; nested exception is com.mongodb.MongoQueryException: Query failed with error code 292 and error message 'Executor error during find command :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in.' on server 192.168.1.198:30014
    at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:138)
    at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2781)
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:2691)
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2411)
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2394)
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:830)
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:816)
    at com.sioo.component.biz.impl.sioovmimpl.VmMessageDtlServiceImpl.listByPageAndCond(VmMessageDtlServiceImpl.java:67)
    at com.sioo.component.biz.impl.sioovmimpl.VmMessageRecordsServiceImpl.findVmMessageDetailsByPage(VmMessageRecordsServiceImpl.java:1113)
    at com.sioo.component.biz.impl.sioovmimpl.VmMessageRecordsServiceImpl$$FastClassBySpringCGLIB$$1df5b259.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
    at com.sioo.component.biz.impl.sioovmimpl.VmMessageRecordsServiceImpl$$EnhancerBySpringCGLIB$$db6911a2.findVmMessageDetailsByPage(<generated>)
    at com.sioo.component.controller.VmMessageController.findVmMessageDetailsByPage(VmMessageController.java:312)
    at com.sioo.component.controller.VmMessageController$$FastClassBySpringCGLIB$$66bdd36.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:100)
    at com.sioo.point.aspect.ShowTimeAspect.dealOldMethod(ShowTimeAspect.java:162)
    at com.sioo.point.aspect.ShowTimeAspect.timeAround(ShowTimeAspect.java:134)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at com.sioo.component.controller.VmMessageController$$EnhancerBySpringCGLIB$$a00b1af3.findVmMessageDetailsByPage(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.mongodb.MongoQueryException: Query failed with error code 292 and error message 'Executor error during find command :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in.' on server 192.168.1.198:30014
    at com.mongodb.operation.FindOperation$1.call(FindOperation.java:706)
    at com.mongodb.operation.FindOperation$1.call(FindOperation.java:695)
    at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:462)
    at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:406)
    at com.mongodb.operation.FindOperation.execute(FindOperation.java:695)
    at com.mongodb.operation.FindOperation.execute(FindOperation.java:83)
    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:179)
    at com.mongodb.client.internal.MongoIterableImpl.execute(MongoIterableImpl.java:132)
    at com.mongodb.client.internal.MongoIterableImpl.iterator(MongoIterableImpl.java:86)
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:2674)
    ... 100 common frames omitted

四、原因

Mongo数据库排序(Sort)阶段默认最大的存储内存限制为100 MB,所以如果要解除限制需要更改聚合操作中的“allowDiskUse ”属性,官方文档见:https://docs.mongodb.com/manual/reference/operator/aggregation/sort/#sort-memory-limit

五、解决方案

使用聚合方式进行条件查询、排序、分页操作

Criteria criteria = commonCond(vmMessageDtlDTO);
// 初始化聚合操作、允许使用磁盘内存缓存
AggregationOptions aggregationOptions = AggregationOptions.builder().allowDiskUse(true).build();
Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.sort(Sort.by(Sort.Direction.DESC, "createTime")),
                Aggregation.skip((long)vmMessageDtlDTO.getCurrentPageIndex()),
                Aggregation.limit(vmMessageDtlDTO.getPageSize())
        ).withOptions(aggregationOptions);
 
List<VmMessageDtlModel> list = mongoTemplate.aggregate(aggregation, VmMessageDtlModel.class, VmMessageDtlModel.class).getMappedResults();

相关文章

  • Java OutOfMemoryError 宕机实验

    概述 JVM OutOfMemoryError(OOME,内存溢出错误)导致宕机的情况有多种,此处主要以超出堆最大...

  • 2.6、内存管理APIs

    1、增量方式分配虚拟内存(堆内存),一次分配一个页。分配内存超出页的范围则增加新页,超出页的操作会发生段错误。在分...

  • 电废人生之 C基础系列20210114

    摸鱼之 在下列几种排序方法中,要求内存量最大的是______。 A快速排序 B插入排序 C选择排序 D归并排序 快...

  • RangeError: Maximum call stack s

    RangeError: Maximum call stack size exceeded(范围错误:超出了最大调用...

  • mongo排序

    升序 sort 1 降序 sort -1 还可以根据多个条件查询 1是升序 -1是降序

  • C,C++内存分配

    C语言内存分配: 静态内存分配,分配内存大小的是固定,问题:1.很容易超出栈内存的最大值 2.为了防止内存不够用会...

  • https配置完成后reload,才能访问https://url

    Firefox报错,错误:SSL 接收到一个超出最大准许长度的记录。 错误代码: SSL_ERROR_RX_REC...

  • python MongoDB基础操作

    连接mongo 插入数据 查询数据 in limit,skip or 删除 更新 排序

  • 安装时填写MongoDB的错误

    错误 解决方案:应该输入mongo

  • 内存一致性错误

    当不同的线程对相同的数据有不同映像时,就发生了内存一致性错误。内存不一致错误的起因很复杂,超出了本课程的范围。好在...

网友评论

      本文标题:Mongo排序超出最大内存错误

      本文链接:https://www.haomeiwen.com/subject/srqphdtx.html