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

NoSQL多对多关系下NOT IN查询的大数据量解决方案咨询

解决方案

针对百万级用户、500万级多对多关系场景,要高效获取1000个与userId=1无关联的用户ID,以下是几种不同NoSQL数据库的落地方案:

MongoDB 方案

MongoDB的聚合管道和索引优化可高效完成查询,核心思路是先定位userId=1的关联用户,再从用户集合中随机筛选排除这些用户的记录。

方案1:分步查询+聚合抽样

先提取userId=1的所有关联用户ID,再通过聚合管道随机抽取符合条件的用户:

// 提取userId=1的全部关联用户ID(利用relation集合的userId单键索引)
var relatedIds = db.relation.distinct("relatedUserId", { userId: 1 });

// 从user集合中随机抽取1000个非关联用户ID
db.user.aggregate([
  { $match: { _id: { $nin: relatedIds } } },
  { $sample: { size: 1000 } },
  { $project: { _id: 1 } }
]);

优化点:给relation.userId和user._id建立单键索引,避免全表扫描。若关联用户数量极大(比如超10万),$nin可能有性能损耗,推荐用下面的聚合管道合并方案。

方案2:聚合管道左连接筛选

通过$lookup关联关系集合,直接筛选出无关联的用户,再随机抽样:

db.user.aggregate([
  {
    $lookup: {
      from: "relation",
      localField: "_id",
      foreignField: "relatedUserId",
      as: "matched_relations",
      pipeline: [{ $match: { userId: 1 } }] // 提前过滤userId=1的关系,减少关联数据量
    }
  },
  { $match: { matched_relations: { $size: 0 } } }, // 筛选无关联的用户
  { $sample: { size: 1000 } },
  { $project: { _id: 1 } }
]);

优势:利用relation(userId, relatedUserId)复合索引,关联阶段只处理userId=1的关系数据,性能更稳定。

Redis 方案

Redis的集合(Set)原生支持高效的差集运算,非常适合这种“取两个集合非交集”的场景:

数据准备

  • 将所有用户ID存入Set集合:SADD user:all 1 2 3 ...(新增用户时同步执行SADD)
  • 将userId=1的关联用户ID存入单独Set:SADD user:1:related 101 102 ...(关联关系新增/删除时同步更新该集合)

查询操作

# 计算全用户集合与关联用户集合的差集,存入临时集合
SDIFFSTORE user:1:unrelated user:all user:1:related

# 从临时集合中随机取出1000个用户ID
SRANDMEMBER user:1:unrelated 1000

# 可选:删除临时集合释放内存
DEL user:1:unrelated

优势:内存级操作,性能极高,百万级集合的差集运算可在毫秒级完成;数据更新逻辑简单,适合高频查询场景。

Cassandra 方案

Cassandra是分布式列存数据库,需结合其数据模型特性设计查询逻辑,避免全集群扫描:

表结构设计

-- 关系表:userId作为分区键,relatedUserId作为聚类键
CREATE TABLE relation (
  userId int,
  relatedUserId int,
  PRIMARY KEY (userId, relatedUserId)
);

-- 用户表:id作为分区键
CREATE TABLE user (
  id int,
  -- 其他用户字段
  PRIMARY KEY (id)
);

查询逻辑

  1. 先获取userId=1的所有关联用户ID:
SELECT relatedUserId FROM relation WHERE userId = 1;
  1. 利用Cassandra的令牌(Token)机制随机查询用户,过滤掉关联ID直到凑够1000个:
-- 生成随机令牌值(可通过Java/Python等SDK获取集群令牌范围后随机生成)
SELECT id FROM user WHERE token(id) > [随机令牌值] LIMIT 2000;

在客户端过滤掉步骤1中得到的关联ID,若数量不足1000,继续生成新的随机令牌重复查询,直到收集足够数量的非关联用户ID。

优势:分布式环境下可水平扩展,通过令牌范围查询避免全集群扫描,适合超大规模数据集场景。

通用优化建议

  • 索引优先:所有NoSQL方案都需要针对查询字段建立合适的索引(MongoDB的复合索引、Redis的Set结构、Cassandra的分区键索引),这是性能保障的核心。
  • 避免全表扫描:无论哪种数据库,都要避免直接遍历全量用户数据后过滤,优先利用数据库原生的集合运算、抽样或范围查询能力。
  • 数据同步:确保用户数据和关系数据的更新能同步到查询依赖的结构(比如Redis的Set、MongoDB的索引),避免查询结果出现数据不一致。

内容的提问来源于stack exchange,提问作者user3246277

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 14:13:11