MongoDB 删除数据方案

我们在日常运营中会积累大量的数据,有时候需要把这些数据归档。

对于MongoDB来说,如果要快速删除大量数据,这里有几种方法可以考虑:

1 deleteMany() - 基础方案

php 复制代码
// 基本用法
db.collection.deleteMany({ status: "inactive" })

// 带条件删除
db.collection.deleteMany({ 
  createdAt: { $lt: new Date("2023-01-01") },
  status: { $in: ["deleted", "expired"] }
})

优点:

  • 简单易用
  • 支持复杂查询条件
  • 返回删除数量

缺点:

  • 删除大量数据时可能很慢
  • 可能阻塞其他操作
  • 内存消耗较大

2 批量删除 - 推荐方案

ini 复制代码
// 分批删除,避免长时间阻塞
function batchDelete(collection, filter, batchSize = 1000) {
  let deletedCount = 0;
  let result;
  
  do {
    result = db[collection].deleteMany(filter, { limit: batchSize });
    deletedCount += result.deletedCount;
    print(`Deleted ${deletedCount} documents so far...`);
    
    // 可选:添加短暂延迟,减少系统压力
    sleep(100);
  } while (result.deletedCount > 0);
  
  return deletedCount;
}

// 使用示例
batchDelete("myCollection", { status: "inactive" }, 5000);

3 使用索引优化

php 复制代码
// 确保查询条件有索引支持
db.collection.createIndex({ status: 1, createdAt: 1 });

// 然后执行删除
db.collection.deleteMany({ 
  status: "inactive", 
  createdAt: { $lt: new Date("2023-01-01") }
});

4 Drop + Recreate - 最快方案(特殊情况)

如果要删除集合中的大部分数据:

php 复制代码
// 如果删除90%以上的数据,考虑这种方式
// 1. 将需要保留的数据导出到新集合
db.oldCollection.aggregate([
  { $match: { status: "active" } },  // 保留条件
  { $out: "newCollection" }
]);

// 2. 删除原集合
db.oldCollection.drop();

// 3. 重命名新集合
db.newCollection.renameCollection("oldCollection");

// 4. 重建索引
db.oldCollection.createIndex({ status: 1 });

5 使用 bulkWrite 优化

ini 复制代码
// 对于有特定_id的批量删除
const idsToDelete = [ObjectId("..."), ObjectId("..."), /* ... */];
const batchSize = 1000;

for (let i = 0; i < idsToDelete.length; i += batchSize) {
  const batch = idsToDelete.slice(i, i + batchSize);
  const operations = batch.map(id => ({
    deleteOne: { filter: { _id: id } }
  }));
  
  db.collection.bulkWrite(operations, { ordered: false });
}

6 性能优化建议

6.1 使用合适的写关注

php 复制代码
db.collection.deleteMany(
  { status: "inactive" },
  { writeConcern: { w: 1, j: false } }  // 减少写确认要求
);

6.2 在低峰期执行

scss 复制代码
// 添加时间检查,在业务低峰期执行
const hour = new Date().getHours();
if (hour >= 2 && hour <= 6) {  // 凌晨2-6点执行
  db.collection.deleteMany({ status: "inactive" });
}

6.3 监控执行进度

javascript 复制代码
// 先统计总数
const totalCount = db.collection.countDocuments({ status: "inactive" });
console.log(`Total documents to delete: ${totalCount}`);

// 执行删除并监控
const result = db.collection.deleteMany({ status: "inactive" });
console.log(`Deleted: ${result.deletedCount} documents`);

总结

  • 小量数据(< 10万) : 直接使用 deleteMany()
  • 中等数据量(10万-100万) : 使用批量删除
  • 大量数据(> 100万) : 考虑 drop+recreate 或分片删除
  • 定期清理: 建议使用 TTL 索引自动删除过期数据
json 复制代码
// TTL索引示例 - 自动删除30天前的数据
db.collection.createIndex(
  { "createdAt": 1 }, 
  { expireAfterSeconds: 30 * 24 * 60 * 60 }  // 30天
);

选择哪种方案主要取决于数据量大小、业务要求和系统资源情况。

相关推荐
豌豆花下猫14 分钟前
Python 潮流周刊#111:Django迎来 20 周年、OpenAI 前员工分享工作体验(摘要)
后端·python·ai
LaoZhangAI30 分钟前
ComfyUI集成GPT-Image-1完全指南:8步实现AI图像创作革命【2025最新】
前端·后端
LaoZhangAI31 分钟前
Cline + Gemini API 完整配置与使用指南【2025最新】
前端·后端
LaoZhangAI43 分钟前
Cline + Claude API 完全指南:2025年智能编程最佳实践
前端·后端
IguoChan3 小时前
9. Redis Operator (2) —— Sentinel部署
后端
ansurfen3 小时前
耗时一周,我的编程语言 Hulo 新增 Bash 转译和包管理工具
后端·编程语言
库森学长3 小时前
索引失效的场景有哪些?
后端·mysql·面试
半夏知半秋4 小时前
CentOS7下的ElasticSearch部署
大数据·服务器·后端·学习·elasticsearch·搜索引擎·全文检索
种子q_q4 小时前
面试官:什么是Spring的三级缓存机制
后端·面试