Tinder如何仅推送未浏览新档案?数据库设计方案探讨
高效获取未浏览用户档案的数据库设计方案
针对你遇到的问题——已浏览10000+档案后,快速获取未浏览的新档案,以下是几个实用的数据库设计方案,避开你提到的低效思路:
一、独立用户浏览关联表(最可靠的方案)
表结构设计
创建一张专门记录用户浏览行为的表,字段极简:
CREATE TABLE user_browsed_profiles ( user_id UUID NOT NULL, browsed_profile_id UUID NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, browsed_profile_id) -- 联合主键,同时作为索引 );
查询逻辑
不用NOT IN,改用NOT EXISTS配合索引快速排除已浏览档案,同时优化随机采样:
-- 先圈定符合条件的目标档案池 WITH eligible_profiles AS ( SELECT profile_id FROM profiles WHERE location = 'Los Angeles' AND gender = 'Female' ) SELECT ep.profile_id FROM eligible_profiles ep WHERE NOT EXISTS ( SELECT 1 FROM user_browsed_profiles ubp WHERE ubp.user_id = '当前用户UUID' AND ubp.browsed_profile_id = ep.profile_id ) -- 用缓存的档案总数计算随机偏移,替代低效的ORDER BY RAND() OFFSET FLOOR(RAND() * ( (SELECT COUNT(*) FROM eligible_profiles) - (SELECT COUNT(*) FROM user_browsed_profiles WHERE user_id = '当前用户UUID') )) LIMIT 10;
优势
- 存储高效:10000条浏览记录仅占几十KB空间,完全无压力;
- 查询高效:联合主键索引让
NOT EXISTS子查询的匹配速度极快,数据库会自动优化为嵌套循环或哈希连接; - 无冗余:每个浏览行为仅存一条记录,不会出现大数组或大元数据问题。
二、布隆过滤器+批量采样(极致性能方案)
核心思路
把用户已浏览的档案ID存入布隆过滤器(内存级数据结构,占用空间极小),每次查询时:
- 从缓存(如Redis)加载当前用户的布隆过滤器;
- 从目标档案池批量查询(如一次查20个);
- 在应用层用布隆过滤器快速过滤已浏览档案,返回未命中的;
- 若数量不足,重复步骤2-3直到凑够10个。
注意点
- 布隆过滤器存在极低的误判率(可通过调整参数降到0.1%以下),偶尔会把未浏览档案当成已浏览的,可配合浏览记录表做二次校验;
- 布隆过滤器无法删除元素,若用户需要“取消浏览”记录,可定期重建过滤器或结合浏览记录表做补偿。
三、随机采样+应用层过滤(轻量实现方案)
适用场景
目标档案池较大但已浏览占比低(如10000/1000000=1%)的情况。
实现逻辑
- 从目标档案池随机采样一批档案(如20个):
SELECT profile_id FROM profiles WHERE location = 'Los Angeles' AND gender = 'Female' ORDER BY RAND() LIMIT 20;
- 在应用层用本地缓存的已浏览ID列表(或布隆过滤器)过滤掉已浏览的;
- 返回剩下的档案,若数量不足则重复采样。
优势
- 实现简单,无需复杂的数据库优化;
- 采样量足够时,大概率能直接凑够10个未浏览档案,查询延迟低。
关键优化技巧
- 给
profiles表的location和gender建联合索引,快速缩小目标档案池范围; - 避免直接用
ORDER BY RAND()(大数据量下慢),优先用缓存的档案总数计算随机偏移量; - 超大规模场景下,可按
location或gender对profiles表做分片,进一步减少单表数据量。
内容的提问来源于stack exchange,提问作者scugn1zz0
相关产品推荐
相关产品推荐

