除了索引之外，MongoDB 在 CRUD 操作优化上还有多种有效策略，尤其在处理海量数据时更为关键。以下是综合各技术文档和实践总结的核心优化方法：

---

### 🔄 一、批量操作优化
1. **使用 `bulkWrite` 替代单条操作**  
   通过批量写入减少网络开销和事务开销。基于 `ReplaceOneModel` 启用 `upsert`，实现存在更新、不存在插入的高效操作：
   ```java
   public void batchSave(List<?> dataList) {
       List<ReplaceOneModel<Document>> bulkOps = dataList.stream()
           .map(item -> {
               Document doc = convertToDocument(item); // 转换为Document
               return new ReplaceOneModel<>(
                   Filters.eq("_id", doc.get("_id")), 
                   doc, 
                   new UpdateOptions().upsert(true)
               );
           }).collect(Collectors.toList());
       collection.bulkWrite(bulkOps); // 批量执行
   }
   ```
   此方法将多条操作合并为一次请求，写入性能提升显著。

---

### 📖 二、分页查询优化
1. **避免精确 `count`**  
   当数据量超大时，`count` 可能极慢。采用阈值法：若跳过 `MAX_PAGE_COUNT`（如1万条）后仍有数据，则返回阈值提示“数据超过1万条”，避免全表扫描：
   ```java
   private long approxCount(MongoTemplate mongoTemplate, Query query) {
       query = query.with(PageRequest.of(MAX_PAGE_COUNT, 1));
       return mongoTemplate.find(query, Entity.class).isEmpty() 
           ? mongoTemplate.count(query) 
           : MAX_PAGE_COUNT;
   }
   。
   ```

2. **用条件替代 `skip`**  
   深度分页时（如第100页），避免 `skip(9900)`。改为记录上一页末尾的排序字段值（如时间戳），作为下一页查询条件：
   ```sql
   -- 原查询：db.collection.find().sort({time:-1}).skip(9900).limit(100)
   -- 优化后：
   db.collection.find({ time: { $lt: lastPageEndTime } })
     .sort({ time: -1 })
     .limit(100);
   ```
   此方法将 **O(N)** 的跳过操作转为 **O(1)** 的条件过滤。

---

### 📤 三、全量导出优化
1. **字段投影减少数据传输**  
   仅查询必要字段，降低网络与内存开销：
   ```java
   Query query = new Query();
   query.fields().include("_id").include("name"); // 只返回_id和name。
   ```

2. **流式处理替代全量加载**  
   使用 `stream()` 逐条处理数据，避免 `findAll` 导致内存溢出：
   ```java
   try (CloseableIterator<Entity> iter = mongoTemplate.stream(query, Entity.class)) {
       while (iter.hasNext()) {
           process(iter.next()); // 单条处理
       }
   }
   ```
   相比分页查询，流式处理无 `skip` 开销，且内存占用恒定。

---

### 🧩 四、文档设计优化
1. **打破第三范式**  
   - **冗余字段**：将高频查询的关联字段（如部门名称）冗余到主文档，避免联表查询。
   - **内嵌设计**：一对多关系直接嵌套子文档（如订单内嵌商品列表），提升读取效率。但需注意文档大小限制（16MB）。
   - **引用设计**：多对多关系使用ID数组而非完整嵌套，避免文档膨胀：
     ```json
     // 学生文档
     {
       "_id": "s001",
       "name": "Alice",
       "teachers": ["t01", "t02"] // 仅存储ID
     }
     ```

---

### ⚙️ 五、分片集群优化
1. **碎片整理（MongoDB <7.0）**  
   在早期版本中，分片集合可能因频繁写入产生碎片化小数据块，导致CRUD延迟。通过 `configureCollectionBalancing` 命令合并数据块，但需注意：
   - 整理期间可能短暂阻塞元数据更新。
   - MongoDB 7.0+ 已支持自动合并，通常无需手动操作。

2. **负载均衡窗口设置**  
   在业务低峰期触发负载均衡器迁移数据块，减少对CRUD的影响。

---

### 💎 六、其他关键技巧
1. **合理控制事务范围**：短事务减少锁竞争。
2. **写入确认级别调整**：对非关键数据使用 `w:0`（无确认），提升写入速度（牺牲一致性）。
3. **TTL索引自动清理**：为临时数据（如日志）设置过期时间，减少存储压力。

---

### 💎 优化方法效果对比表
| **优化方向**       | **适用场景**               | **性能提升效果**       | **实现复杂度** |
|--------------------|--------------------------|----------------------|--------------|
| **批量写入**       | 数据导入、批量更新         | ⭐⭐⭐⭐⭐ (极高)         | ⭐⭐ (中等)    |
| **流式导出**       | 大数据量导出              | ⭐⭐⭐⭐ (避免OOM)       | ⭐ (简单)     |
| **条件分页**       | 深度分页（>100页）        | ⭐⭐⭐⭐ (O(1) 跳转)     | ⭐⭐ (中等)    |
| **冗余字段**       | 高频关联查询              | ⭐⭐⭐ (减少联表)        | ⭐⭐⭐ (较高)   |
| **分片碎片整理**   | MongoDB 6.0以下分片集群   | ⭐⭐ (减少延迟)         | ⭐⭐⭐⭐ (复杂) |

---

> 💡 **实践建议**：优先从**批量操作**和**分页策略**入手，这两类优化代码改动小且收益显著。海量数据场景下，**流式处理+字段投影**是导出标配方案。分片集群升级到 MongoDB 7.0+ 可减少运维负担。