数据库做字段冗余好还是数据实时生成好?

有这样一个需求:记录一篇文章的收藏记录。

所以需要有两个表,一个是“文章表”,一个是“收藏记录表”。
读取该文章后需要读取出该文章的收藏数量。

有两种解决方案:
1.文章里有“收藏数量”字段,每当一位用户收藏该文章,就将该字段+1,同时往“收藏记录表”中添加一条收藏记录。
优点是在读取文章的时候,不需要联表查询它的收藏记录;缺点是进行收藏操作的时候需要写两张表,并且会多一个字段的冗余。

2.文章里没有“收藏数量”字段,当用户收藏该文章,只会往“收藏记录表”中添加一条收藏记录。
优点是,收藏的时候只需要写一张表,而且没有字段冗余;缺点是读取的时候需要联表查询,可能效率也不是很高。

请问这两个方案哪一个更好呢?

阅读 5.6k
9 个回答

建议使用冗余,空间是不值钱的,效率是值钱的,真正的企业级数据库里一定有数据冗余,没有必要一定遵循数据库设计的那几大范式

主要看具体业务需求,不过更推荐方案一。

首先,字段的冗余并不是一个多大的缺点,另外,用事务来实现多表操作也很方便。

而方案一带来的好处除了查询效率高,最关键的是支持的业务场景更多,虽然现在看,收藏数好像也不是个重要字段,但是某天产品突然加需求说,咱们要按收藏数来个排序,分页等各种,这时候用方案二实现起来就会越来越恶心

第一种方案缺点你也说了,所以这里不赘述了;补充下就是还会涉及到事务、锁等。
第二种方案在某种程度上也行,但是如果用到count,收藏稍微频繁点,mysql的count比较坑。
我的建议是你在第二种的基础上分两步:

  1. 获取文章
  2. 获取收藏数量

简单的说就是不要把收藏数量和文档放到一个接口,分开。
未来如果性能不好了加缓存也好加了。

建议题主使用redisincr命令

  1. Redis incr 可以实现原子性的递增,可应用于高并发
  2. 利用缓存可缓解请求数据对数据库的直接施压

第一个吧,一个字段根本不占用什么空间。
事务还有锁啥的,其实不必考虑。这个数又不是账户余额。错几个也没什么大不了的嘛。

设计根据业务来吧,收藏数量这种业务根本不是特别重要,你放把收藏数放内存里都可以,分布式的话放缓存里

常用字段的话建议用冗余

如果列表需要显示收藏数(废话)。显然方案二需要count查询多次。收藏数量大了之后会消耗性能。所以建议方案一。方案一如果用事务用锁(解决数量不一致?)。就太小题大做了。我觉得不需要用事务,可能会导致数目与列表不一致。但是用户会在乎这个吗

建议用方案一,同时配合使用redis,这个当然要看网站的规模了,利用redis存储文章的收藏量信息,需要更新收藏量信息时,先写入redis,再定时写数据库

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题