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

EF Core中高效统计一对多关联数量的最优方案探讨

问题背景

在Entity Framework Core(EF Core)中,我有两个模型:CreatorPost和Like。每个帖子可被无限点赞,但每个点赞仅属于一个帖子,为一对多关联:

public class CreatorPost
{
    ...
}
public class Like
{
    ...
    public CreatorPost CreatorPost { get; set; }
}

在展示帖子时,我通过以下方式获取点赞数:

int likes = _context.Likes.Where(l => l.CreatorPost == creatorPost).Count();

由于所有帖子的点赞都存储在同一张表中,随着点赞数量增加,查询点赞数的耗时会越来越长。

尝试的解决方案

我尝试的方案是为CreatorPost新增一个字段,用于存储点赞数:

public class CreatorPost
{
    ...
    public uint Likes { get; set; } // Added this
}

此后,获取帖子点赞数时无需查询所有点赞记录,直接读取该字段即可。同时在添加点赞的LikeCreatorPost()方法中,增加代码使该字段值加1。

目前获取点赞数的逻辑正常,但在LikeCreatorPost()方法中,为防止用户重复点赞,仍需查询所有点赞记录进行校验。


问题解答

1. 新增字段的性能提升幅度

原方案的Count()查询需要扫描Like表中对应目标帖子的所有记录,数据量越大(比如百万级点赞数据),查询耗时会呈线性增长,可能从几毫秒涨到几十甚至上百毫秒。而新增Likes字段后,读取点赞数是直接从CreatorPost表读取单条记录的字段,属于O(1)的常量级操作,耗时可以控制在1毫秒以内,性能提升非常显著,尤其是高频展示帖子的场景。

2. 此举是否值得

完全值得。点赞数是页面展示的高频读取字段,优化这个场景能直接降低数据库的查询负载,提升页面响应速度。虽然需要在点赞/取消点赞时同步更新Likes字段,但这个额外的写操作开销极小,和读操作的性能收益相比可以忽略不计。唯一需要注意的是保证数据一致性,比如要在同一个事务中完成添加/删除Like记录和更新Likes字段的操作,避免出现数据不一致的情况。

3. 更高效的解决方案

  • 优化重复点赞校验:给Like表添加UserId(假设点赞关联用户)和CreatorPostId的联合唯一索引。这样校验用户是否已点赞时,查询会直接走索引查找,而非全表扫描,速度会大幅提升,同时数据库层面也能避免重复数据插入。
  • 异步更新点赞数:如果业务允许点赞数存在短暂的延迟,可以使用消息队列异步更新Likes字段。用户点赞后先写入Like记录,再发送消息到队列,后台服务消费消息批量更新帖子的点赞数,能减少实时写操作的数据库压力,适合高并发场景。
  • 缓存层优化:即使有了Likes字段,也可以将帖子的点赞数缓存到Redis等缓存服务中。展示页面时优先读取缓存,缓存失效后再从数据库读取并更新缓存,进一步降低数据库的查询压力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 01:57:36