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天
);

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

相关推荐
_風箏21 分钟前
Zabbix【问题 01】安装问题 (比 zabbix-release-5.0-1.el7.noarch 还要新) 问题处理
后端
卓码软件测评27 分钟前
网站测评-利用缓存机制实现XSS的分步测试方法
java·后端·安全·spring·可用性测试·软件需求
星星电灯猴28 分钟前
一次真实的 TF 上架协作案例,从证书到分发的多工具配合流程
后端
Cosolar1 小时前
玩转 WSL:Windows 一键开启 Linux 子系统,轻松实现 SSH 远程连接
后端
rannn_1111 小时前
【Linux学习|黑马笔记|Day4】IP地址、主机名、网络请求、下载、端口、进程管理、主机状态监控、环境变量、文件的上传和下载、压缩和解压
linux·笔记·后端·学习
惜鸟1 小时前
如何让大模型输出结构化数据
后端
ApeAssistant1 小时前
windows 端口占用解决方案
服务器·后端
阿湯哥1 小时前
SkyPilot 的产生背景
后端·python·flask
吴佳浩1 小时前
Python 环境管理工具完全指南
后端·python
JohnYan2 小时前
工作笔记 - 一次微信认证集成迁移
后端·安全·微信