为什么我们放弃使用MongoDB

在面临MongoDB存储限制及资源浪费的问题后,团队决定转向使用MapReduce进行大数据量计算,仅在必要时运行,计算完成后将结果存入MySQL,以此优化资源利用并满足业务需求。

     公司开始新项目时部分数据服务选择使用MongoDB,而且在同事内部作了MongoDB应用的扫盲介绍,当时貌似Mysql派和MongoDB派相互之间都没有能说服对方,所以MongoDB的使用就一直延续下来。直到几天前,在考虑系统上线发布和运营时,一些问题出现了。

 

1.MongoDB存储文件会急剧增大,如果使用32位操作系统很容易达到单个文件体积上限。所以对于MongoDB必须使用64位操作系统,而在亚马逊的EC2中只有是large以上类型的instanceCPU才是64位。

2.MongoDB一般都推荐是多点部署,互为镜像,这样保证服务的延续性和数据的安全性。所以如果需要提供稳定的服务,至少需要2EC2instance来作MongoDB服务。而实际对于我们大数据量计算操作可能在一天内累计只有大概1小时,其余时间更多只是少量数据查询操作。

 

      综合以上两点,如果继续使用MongoDB,至少需要两台large以上instance,并且是7X24小时运行,感觉是对运算能力的浪费。

      再三讨论后我们决定暂时放弃MongoDB, 将这部分的运算改为使用MapReduce 来处理。亚马逊的MapReduce可以充分体现按需使用运算能力的特性,在使用MapReduce完成所有计算需要后,再将需要查询使用的结果数据导入到Mysql数据库中。这样即满足了那1小时内需要的运行能力,又满足了其余时间对计算结果的查询需求。

 

      通过以上的事例,说明在使用云计算平台时,对程序开发技术的选型必须充分考虑到平台能够提供虚拟硬件设备的技术指标。并且需要转变以往的设计思路,更多考虑到云平台方便启动和关闭instance的特性。尽量减少7X24长时间使用相同一台instance作服务的应用,如果这样的服务无法避免时,应该考虑多台冗余,并在程序设计中去除对instance的内网ip地址耦合,当某台instance出现故障而需要更新新的instance时,内网ip 地址变化不会导致程序无法正常运行。

<think>嗯,用户想知道MongoDB中getMore命令不使用主键的原因以及如何优化。首先,我需要回忆一下getMore命令的作用。getMore通常用于分批次获取大量查询结果,比如在游标遍历时。用户提到不走主键,这可能涉及到查询是否有效利用了索引,尤其是主键索引。 首先,为什么getMore可能不走主键?可能的情况包括:查询本身没有使用索引,或者虽然用了索引,但在分页或排序时无法有效利用主键。比如,如果查询包含排序,但排序字段不是主键的一部分,这时候可能无法使用主键索引,导致全表扫描。另外,如果查询条件没有覆盖主键,自然也不会用上主键索引。 接下来是优化方法。用户提到的引用里提到慢查询日志和执行计划分析,这可能和优化有关。比如,通过分析慢查询日志找到getMore操作,查看其执行计划是否缺少索引。然后,可能需要优化索引,比如创建复合索引或者覆盖索引。此外,调整batchSize也可能有帮助,减少每批的数据量,减轻服务器压力,避免锁竞争。 还要考虑是否查询语句本身有问题,比如不必要的结果集排序或者投影,导致无法使用主键。另外,分片集群的情况,如果数据分布不均,也可能影响getMore的性能,这时候可能需要调整分片策略。 需要确认用户的具体情况,比如是否有合适的索引,查询条件如何,数据量大小,是否分片等。但根据现有引用,优化方法可能包括检查执行计划、优化索引、调整batchSize、数据分片等。要确保用户理解如何通过分析执行计划和慢查询日志来定位问题,然后针对性地调整索引或查询参数。</think>### MongoDB getMore 命令不走主键的原因及优化方法 #### 一、getMore 命令不走主键的常见原因 1. **查询未命中索引** - 若查询条件未包含主键字段(`_id`),或未定义覆盖查询的复合索引,MongoDB 可能选择全集合扫描而非主键索引[^2]。 - **示例**:查询 `{age: 25}` 时若未对 `age` 建立索引,即使 `_id` 是主键,也不会被使用。 2. **排序或分页操作** - 当查询包含排序(`sort`)且排序字段与主键无关时,可能导致放弃主键索引。例如 `sort({timestamp: -1})` 若未建立 `timestamp` 索引,可能触发内存排序或全表扫描[^3]。 3. **投影或聚合阶段影响** - 若查询包含复杂聚合(如 `$group`)或特定投影(`projection`),可能导致索引覆盖失效,从而无法利用主键索引[^1]。 --- #### 二、优化方法 1. **索引优化** - **创建复合索引**:针对查询条件、排序字段和投影字段建立复合索引。例如,对查询 `find({age:25}).sort({timestamp:-1})` 建立索引 `{age:1, timestamp:-1}`[^1]。 - **覆盖索引**:确保索引包含所有查询字段,避免回表查询。通过 `explain()` 检查是否出现 `IXSCAN`(索引扫描)和 `PROJECTION_COVERED`[^2]。 ```javascript // 示例:检查执行计划 db.collection.find({age:25}).sort({timestamp:-1}).explain("executionStats"); ``` 2. **调整批处理参数** - **减小 `batchSize`**:降低单个 `getMore` 请求的数据量,减少锁竞争和内存压力。例如将默认的 101 条调整为 50 条[^3]。 ```javascript // 示例:设置 batchSize cursor = db.collection.find().batchSize(50); ``` 3. **查询语句优化** - **避免内存排序**:通过索引保证排序顺序,防止出现 `SORT` 阶段(内存排序)。 - **限制返回字段**:使用投影仅返回必要字段,减少数据传输和内存占用。 4. **分片集群优化** - 若集合已分片,确保分片键与查询条件高度相关。例如,对按 `region` 分片的集合查询 `{region: "Asia"}` 可显著提升性能[^1]。 --- #### 三、诊断工具 1. **慢查询日志分析** - 启用 Profiler 记录慢查询,筛选 `command: getMore` 操作,分析其 `planSummary` 和 `executionStats`[^2]。 ```javascript // 启用 Profiler db.setProfilingLevel(2, {slowms: 100}); ``` 2. **执行计划解读** - 关注 `winningPlan` 中是否包含 `IDHACK`(主键索引优化),若未出现则说明未使用主键索引[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值