mysql如何实现点赞收藏功能_mysql社交项目案例

来源:这里教程网 时间:2026-02-28 20:49:28 作者:

点赞和收藏为什么要分开建表

因为点赞(like)和收藏(favorite)虽然行为相似,但业务语义、查询频率、生命周期都不同。混在一张表里会导致索引低效、权限难控制、统计逻辑耦合。比如用户取消点赞很频繁,但收藏删除率低;又比如「我收藏了哪些文章」要常查,而「谁点过这个评论」可能只在后台用。分开后,

likes
表可以加
(user_id, target_type, target_id)
联合唯一索引防重复,
favorites
表则更适合加
created_at
降序索引支持「最近收藏」。

如何避免重复点赞或重复收藏

核心是靠数据库层唯一约束,不是靠应用层判断。否则并发请求下容易写入两条。建表时必须声明:

CREATE TABLE likes (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_id BIGINT NOT NULL,
  target_type VARCHAR(20) NOT NULL COMMENT 'post, comment, reply',
  target_id BIGINT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_user_target (user_id, target_type, target_id)
);

执行

INSERT INTO likes (user_id, target_type, target_id) VALUES (123, 'post', 456)
时,如果已存在相同三元组,MySQL 直接报错
ERROR 1062 (23000): Duplicate entry '123-post-456' for key 'uk_user_target'
。应用层捕获这个错误,返回「已点过赞」即可。

怎么高效查某篇文章的点赞数和是否被当前用户点过赞

不能每次查都

COUNT(*)
全表扫描,也不能用两个独立查询(N+1 问题)。推荐用单条 SQL + 条件聚合:

SELECT 
  COUNT(*) AS like_count,
  MAX(CASE WHEN user_id = 123 THEN 1 ELSE 0 END) AS has_liked
FROM likes 
WHERE target_type = 'post' AND target_id = 456;

这个查询能命中

uk_user_target
索引的前缀(
target_type, target_id
),性能可控。注意:如果
likes
表数据量超千万,建议把计数结果缓存到 Redis,只在点赞/取消时更新缓存和 DB。

收藏表要不要记录来源渠道或设备信息

一般不需要。收藏本质是用户对内容的长期兴趣标记,和操作路径无关。加

source
device_id
字段只会增大索引体积、拖慢写入,且几乎没查询场景用到。例外情况只有做反作弊——比如限制同一设备 1 小时内最多收藏 10 篇,这时才需要,但应单独建轻量级风控日志表,而不是污染主收藏表。

实际部署时最容易被忽略的是:没有给
target_type
字段加枚举校验或应用层白名单控制。一旦写入非法值如
'post_xxx'
或拼写错误的
'posst'
,后续所有按类型聚合的统计都会漏数据,而且很难回溯修复。

相关推荐