MySQL中存储点赞/点踩的Boolean与SmallInteger方案对比咨询
两种MySQL点赞/点踩存储方案的分析与建议
Boolean方案(likes表)
这个方案用布尔值记录明确的投票动作,取消投票就删除对应记录,特点非常鲜明:
- 优势:
- 数据极简,每条记录都对应有效的投票状态,没有冗余的0值数据
user_id + recipe_id的唯一约束直接保证用户对同一内容只能投一次,从根源避免重复数据- 统计赞/踩数量效率极高:赞数用
SUM(liked),踩数用COUNT(*) - SUM(liked),MySQL能快速计算 - 取消投票逻辑简单,直接删除记录即可,不会留下无效数据
- 劣势:
- 完全无法追踪用户的投票变更历史,比如用户赞了又取消、取消后又点赞,删除记录后就没有任何操作痕迹
- 判断用户当前投票状态需要两步:先查询是否存在记录,再判断
liked字段值,比直接查数值字段多一层判断
SmallInteger方案(votes表)
这个方案用数值覆盖所有投票状态(1=点赞,-1=点踩,0=取消投票),取消投票仅更新字段值,适合需要追踪状态变化的场景:
- 优势:
- 完整保留用户的投票状态变更轨迹,所有操作都是更新记录,不会丢失历史操作数据
- 判断用户当前状态更直接,只需查询
vote字段的值,无需额外判断记录是否存在 - 统计总净票数(点赞数-点踩数)可以直接用
SUM(vote)一步到位
- 劣势:
- 必须手动添加
user_id + recipe_id的唯一约束,否则会出现同一用户对同一内容的多条记录,直接导致统计结果错误 - 会存在
vote=0的无效记录,虽然单条数据占用空间极小,但数据量较大时仍会浪费存储资源 - 统计赞/踩数量的语句稍复杂,需要用条件求和:赞数用
SUM(CASE WHEN vote=1 THEN 1 ELSE 0 END),踩数用SUM(CASE WHEN vote=-1 THEN 1 ELSE 0 END),不过MySQL优化后性能差异可以忽略
- 必须手动添加
方案选择建议
- 如果业务仅需记录用户当前的投票状态,不需要追踪变更历史,优先选Boolean方案,数据干净、维护成本低、统计效率高
- 如果需要支持用户多次切换投票状态,或者要分析用户的投票行为轨迹(比如统计用户修改投票的次数),就选SmallInteger方案,记得一定要添加唯一约束,并且给
vote字段加合法值限制(MySQL 8.0+可用CHECK (vote IN (-1,0,1)),低版本用ENUM类型替代)
内容的提问来源于stack exchange,提问作者dmytroshved
相关产品推荐
相关产品推荐

