什么是良好的数据库结构,用于跟踪谁已阅读哪些消息?

时间:2017-07-29 02:03:15

标签: database algorithm

在Stack Overflow等消息传递论坛中,有哪些有效的方法来存储数据以跟踪谁已阅读哪些消息?

如果有m条消息和n个用户,是否可能出现最差小于m * n位的情况?

2 个答案:

答案 0 :(得分:1)

我将使用经典的READ_MESSAGES表。

-----FK---------FK------------------------------------
|  msg_id  |  user_id  | read_timestamp  |  blah...
------------------------------------------------------
 \========PK==========/

这将有效达到一百万行左右。插入将成为一种痛苦。如果我们使用类似MySQL的东西,那么我们需要一个人工自动增量主键。

-------------------FK---------FK----------------------------------
|  autoinc_pk |  msg_id  |  user_id  | read_timestamp  |  blah...
------------------------------------------------------------------
\=====PK=====/ \===UNIQUE=NOT=NULL===/

这将捕获我们的数据,但可能不是查询的最佳选择。我们有两种可能的方式:

  1. 鉴于message id显示哪些或哪些用户已阅读它。 SELECT msg_id, COUNT(user_id) FROM read_messages WHERE msg_id='123'
  2. 给定user id显示已读取的消息数量。 SELECT user_id, COUNT(msg_id) FROM read_messages WHERE user_id='456'
  3. 当然系统需要执行两种类型的查询,但如果它比其他类型的查询方式更多,那么我们可以调整设计以使这些查询更快一些。这是通过更改UNIQUE-NOT-NULL键中列的顺序来完成的。 Idea位于两列之外,首先放置具有给定值的列,换句话说,首先放置WHERE子句中出现的列。

    因此,如果我们发现系统执行了更多Type-1查询,那么Type-2查询,我们将按{msg_id, user_id}排序列,否则我们将其命名为{user_id, msg_id}。请记住,当我们对多列密钥执行WHERE查询时,第一列有利于速度。

    如果我们确实发现我们的应用程序更倾向于支持一种类型的查询,那么我们可以进一步在WHERE子句中的列上水平分区/分区表。在像Cassandra或DynamoDB这样的数据库中,它可能是分区键。

答案 1 :(得分:0)

如果您需要一个真正可扩展的解决方案,并且出于某种原因,简单的sql表对您不起作用,可以选择DynamoDB:

拥有一个包含用户ID主键和消息ID范围键的表。还要创建一个全局二级索引,主键为消息ID,范围键为用户ID。现在,您可以轻松地执行您可能需要的任何类型的查询(例如:获取用户X读取的消息,获取读取消息Y的用户,或者用户X读取消息Y)。该解决方案具有可扩展性并具有恒定,可预测的速度。缺点是它可能比sql更昂贵。