数据库中为每个用户建立一张表是否更合适?

场景如下:
购物网站想要记录每个用户的浏览历史,用户可以查询自己的浏览历史,浏览历史的长度为50。

把所有记录都记在一张表table_total的情况:
每条浏览记录的数据格式为:(user_id, item_id, time) 假设网站的用户人数为: 1,000,000,table_total的最大tupple数应该为:n=50*1,000,000。在user_id上建立索引。

  1. 某用户查询时的复杂度:select * from table_total where user_id = curent_user_id 有索引的情况下复杂度为:log(n)。

  2. 某用户插入时的复杂度:因为需要知道用户的浏览历史是否大于50,如果大于50了需要把最老的那条记录删除所以也需要先:select * from table_total where user_id = curent_user_id,再判断数据长度是否需要更新。复杂度为:log(n)

每个用户的记录单独存在一个表table_userid的情况:
在用户登录时就记录下用户的对应的userid,每个表中的attributes为:(item_id,time)依照time的值来排序,并且每个表的最大长度都为50。

  1. 某用户查询时的复杂度:select * from table_userid。复杂度为:<50

  2. 某用户插入时的复杂度:查看表的长度,等于50,删除表中最后一项,插入;小于50,直接插入。复杂度:<2

如果实时同时在线用户数量为10,000,这些用户平均每分钟每人浏览3个items。那么每分钟就有30,000个插入请求产生,这个量应该很大了吧?

问题1:为每个用户单独建立一张表会占用更多的磁盘空间吗?因为一张表时的大小为:3*50*1,000,000 另外索引还要单独占有空间;而每个用户一张表时的大小为:1,000,000*50*2,再加上每张表所需要的额外空间。这么对比一下,如果用户量足够大貌似后者比前者占有的空间要小。

问题2:对比查询和插入的效率都是后者要高一些,而且后者不同的表可以部署在不同的数据库服务器上实现多线程运行,那么这种实现方式到底可不可靠?为什么查询相关问题时这么实现的人都被鄙视啊?

问题3:为每一个用户建立一张表的做法会有这个问题就是表太小了,展现不出数据库的优势,那么干脆就用文件来储存就好了。实际中是不是这么实现的呢?

阅读 11.8k
4 个回答

感觉把问题复杂化了,第一,历史记录的保存一般是以时间为基线实现的,半年,一年...,以此类推可能分成多个历史库,第二,一般会使用读写分离的方式,也就是历史订单和当前订单是分离,按时间线定期进行备份迁移,所以很少看到你说的这种情况

我觉得可以的

感谢@西西 提示的NoSQL,在实际场景中应该是使用NoSQL来存储相应的数据结构的。因为在传统的关系型数据库中对数据格式的要求太严格了,在这个场景中数据的格式应该是:

  1. user1

    • item1 datetime

    • item2 datetime

  2. user2

    • item1 datetime

    • item2 datetime

    • item3 datetime

在传统的关系型数据库中只能这么存储:
user1 item1 datetime
user1 item2 datetime
user2 item1 datetime
user2 item2 datetime
user2 item3 datetime
很明显这样的数据结构不利于查询和更新,而上面的数据结构如果实现了对每个用户下面的item条目的更新和插入操作,那么查询的请求会非常快。所以应用NoSQL应该是比较好的方法。

因为没有真正做过很大的项目,所以不敢肯定是不是最好的答案,先放在这里供大家批评吧。有大牛愿意讲解一下最好了。

不建议这样做。
个人认为更好的办法是用户的基本信息存放到一张表中DimUser,所有用户的浏览记录存放到另一张表中FactHistory,两张表通过用户id字段UserId进行关联,无论增删改查还是优化都相对要好一些。

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