MongoDB查询优化:从10s到10ms

本文通过一个实际案例,分析了MongoDB查询慢的问题,探讨了如何从10秒优化到10毫秒的过程。问题涉及查询计划的选择、索引使用以及强制索引对查询效率的影响,最终提出了解决方案,强调了线下调试环境和源码理解的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【摘要】本文是我前同事付秋雷最近遇到到一个关于MongoDB执行计划选择的问题,非常有意思,在探索源码之后,他将整个问题搞明白并整理分享出来。付秋雷曾是Tair(阿里内部用得非常广泛的KV存储系统)的核心开发成员,目前就职于蘑菇街。

背景

苏先生反馈线上某条查询很慢(10+ seconds),语句相当于:

db.myColl.find({app:"my_app",requestTime:{$gte:1492502247000,$lt:1492588800000}}).sort({_id:-1}).limit(1)

myColl这个collection中的记录内容类似于:

{ "_id" : ObjectId("58fd895359cb8757d493ce60"), "app" : "my_app", "eventId" : 141761066, "requestTime" : NumberLong("1493010771753"), "scene" : "scene01" }
{ "_id" : ObjectId("58fd895359cb8757d493ce52"), "app" : "my_app", "eventId" : 141761052, "requestTime" : NumberLong("1493010771528"), "scene" : "scene02" }
{ "_id" : ObjectId("58fd895359cb8757d493ce36"), "app" : "my_app", "eventId" : 141761024, "requestTime" : NumberLong("1493010771348"), "scene" : "scene03" }
{ "_id" : ObjectId("58fd895359cb8757d493ce31"), "app" : "my_app", "eventId" : 141761019, "requestTime" : NumberLong("1493010771303"), "scene" : "scene01" }
{ "_id" : ObjectId("58fd895359cb8757d493ce2d"), "app" : "my_app", "eventId" : 141761015, "requestTime" : NumberLong("1493010771257"), "scene" : "scene01" }
{ "_id" : ObjectId("58fd895259cb8757d493ce10"), "app" : "my_app", "eventId" : 141760986, "requestTime" : NumberLong("1493010770866"), "scene" : "scene01" }
{ "_id" : ObjectId("58fd895259cb8757d493ce09"), "app" : "my_app", "eventId" : 141760979, "requestTime" : NumberLong("1493010770757"), "scene" : "scene01" }
{ "_id" : ObjectId("58fd895259cb8757d493ce02"), "app" : "my_app", "eventId" : 141760972, "requestTime" : NumberLong("1493010770614"), "scene" : "scene03" }
{ "_id" : ObjectId("58fd895259cb8757d493cdf1"), "app
server: ssl: enabled: true key-store-type: PKCS12 key-store: classpath:keystores.p12 key-store-password: abc1234 jetty: threads: #acceptors线程池用于接受Http请求 acceptors: 4 #selectors线程池用于处理HTTP数据包 selectors: 8 #worker线程池负责调用Web方法 min: 8 max: 200 port: 7700 servlet: context-path: /his-api spring: servlet: multipart: #允许上传文件 enabled: true #每个文件最大不能超过20M max-file-size: 20MB #HTTP请求不能超过20M max-request-size: 20MB datasource: type: com.alibaba.druid.pool.DruidDataSource druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.67.88:3306/HIS系统?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true username: root password: 123456 initial-size: 8 max-active: 16 min-idle: 8 max-wait: 6000 test-while-idle: true test-on-borrow: true test-on-return: false validation-query: SELECT 1 data: mongodb: host: localhost port: 27017 database: his #admin是MongoDb用于验证用户身份的逻辑库 authentication-database: admin username: password: #二级缓存 cache: redis: #缓存一个月时间 time-to-live: 259000000 type: redis rabbitmq: host: localhost port: 15672 username: guest password: guest redis: database: 0 host: localhost port: 6379 password: jedis: pool: #连接超时的最大时间 max-active: 1000 #等待空闲连接的最大空间 max-wait: -1ms max-idle: 16 min-idle: 8 mybatis: mapper-locations: classpath*:mapper/*.xml type-aliases-package: com.sky.his.api.db.pojo configuration: #输出执行的sql语句 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true logging: level: #springBoot的日志级别 root: info #mybatis的日志级别 com.sky.his.api.db.dao: warn pattern: console: "%d{yyyy/MM/dd HH:mm:ss} %-5level %msg%n" sa-token: #HTTP请求头中哪个属性用来上传令牌 token-name: token #过期时间(秒),设置为30天 timeout: 2592000 #临时有效期,设置为3天 activity-timeout: 259200 #不允许相同账号同时在线,新登陆的账号会挤掉原来登陆的账号 allow-concurrent-login: false #在多人登陆相同账号的时候,是否使用相同的Token is-share: false token-style: uuid #是否读取Cookie中的令牌 isReadCookie: false #同端互斥 isConcurrent: false #SaToken缓存令牌用其他的逻辑库,避免业务数据和令牌数据共用相同的Redis逻辑库 alone-redis: database: 1 host: localhost port: 6379 password: timeout: 10s lettuce: pool: # 连接池最大连接数 max-active: 200 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: 10s # 连接池中的最大空闲连接 max-idle: 16 # 连接池中的最小空闲连接 min-idle: 8 minio: endpoint: http://127.0.0.1:9090 access-key: hiPqGAOC2TzICJraqOkp secret-key: Ky3CZbXBbnC5oBbqcUHv5MLtRSobVrBfrxY7400o bucket: his tencent: cloud: appId: 1321618234 secretId: AKIDjLjtpY2HI6jANPEqDMHILBqK9qPrCTen secretKey: 5yd6hKrJYZR8bJzVoxsb7CCzZF2cy72k face: groupId: his region: ap-beijing im: sdkAppId: 1600065143 secretKey: cc02531709a220c67be070e81535d585f537277dbf05016363be07b00709cdd3 managerId: administrator customerServiceId: customer_service_1 #wechat: # app-id: APPID # app-secret: 秘钥 # pay: # v3: # his-vue: # app-id: APPID # app-v3-secret: 微信支付3.0接口秘钥 # mch-id: 微信商户平台id # domain: URL回调地址 # cert-path: apiclient_cert.p12 huawei: appKey: 123 appSecret: 12 根据这个配置文件部署项目,写出详细的部署步骤
05-13
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值