You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB $in操作性能阈值及百万级拉黑用户Schema优化咨询

用户拉黑功能的数据库性能与Schema设计问题解答

一、$in操作何时会变慢?

$in操作的性能下降阈值没有绝对固定值,主要取决于数据库版本、集合数据量、索引情况,但实际业务中通常当数组长度超过5000-10000条时,性能会出现明显下滑:

  • 数组越大,数据库需要遍历匹配的元素越多,内存占用会显著上升;
  • 若查询字段未建索引,大数组的$in会触发全表扫描,性能暴跌;
  • 即使有索引,过大的数组也会降低索引的匹配效率,尤其是结合其他查询条件时。

二、单用户最多拉黑10万用户的可扩展Schema设计

绝对不能将拉黑列表存在用户文档的数组字段中(哪怕单文档大小没到数据库的存储限制),大数组的$in查询和数组更新都会成为性能瓶颈。推荐采用独立的拉黑关系集合方案:

1. 新建拉黑关系集合(如user_blocks)

每个文档存储一条拉黑记录,结构如下:

{
  blocker_id: ObjectId("用户ID"),   // 执行拉黑操作的用户ID
  blocked_id: ObjectId("用户ID"),   // 被拉黑的用户ID
  created_at: ISODate("2024-05-20T12:00:00Z")  // 可选,记录拉黑时间
}

2. 必加索引优化

  • 给blocker_id建单键索引:快速查询某用户的所有拉黑记录;
  • 给{ blocker_id: 1, blocked_id: 1 }建复合唯一索引:防止同一用户重复拉黑同一目标,同时加速“检查某用户是否被拉黑”的查询。

3. 查询与操作适配调整

  • 检查单个用户是否被拉黑:直接查询user_blocks集合,利用复合索引,速度极快:
    db.user_blocks.findOne({ blocker_id: 当前用户ID, blocked_id: 目标用户ID })
    
  • 查询排除被拉黑用户的内容:先通过blocker_id索引获取当前用户的所有被拉黑ID列表,再在目标集合(如帖子、评论)中用$nin过滤;若列表过大,可改用聚合$lookup关联查询,避免内存过载;
  • 批量拉黑/取消拉黑:批量插入或删除user_blocks中的对应文档,比更新用户数组更高效且避免锁文档。

4. 辅助优化(可选)

若需要频繁展示用户拉黑数量,可在用户文档中维护一个block_count字段,每次拉黑/取消拉黑时同步更新该字段,避免每次都执行count()查询。

内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 12:55:22