如何设计引用多个表的灵活MySQL通知模式?

Isa*_*kew 0 php mysql schema notifications

我决定使用另一个StackOverflow帖子的灵感来建立一个通知系统,该帖子建议我从通知正文中分解通知.因此,我有以下架构:

notifications
id | user_id | notification_object_id | is_read

notification_objects
id | message | type
Run Code Online (Sandbox Code Playgroud)

我已经设置了这种方式,因此我可以创建一个通知对象,并在通知对象适用于多个人的情况下将其发送给多个用户.类型是按类型将消息压缩成一个通知,类似于Facebook所说的方式,"John Doe,John Smith和其他27个用户评论......"而不是给你29个单独的通知.

(表和列的命名方案适用于CakePHP 3的'包含')

我需要帮助的是一种方法来绑定将在请求中扮演角色的不同用户或对象.用户可能已经评论过,因此我可能需要消息的用户的user_id,并且需要将其存储在某处.

除了用户之外还有其他情况; 人们可能想知道评论的ID,以便他可以点击通知并直接发表评论/ 81.我有很多用例,我想将不同类型的id存储为其他表(用户,评论,文章等)的外键,其中一些可能需要两个外键(比如说你想提及" Chris has评论了你的文章 '如何向StackOverflow寻求帮助'",并为Chris提供了user_id,并在通知中链接了文章的文章ID.

每种不同类型的通知都可以具有从中提取信息所需的不同值和表.什么是开始创建此架构的好地方?

hel*_*ert 11

我将尝试从面向对象的角度回答这个问题.当在讲阶级,而不是,你可能会喜欢的东西一开始AbstractNotificationObject的基本属性(日期,时间,也许一个消息)和若干专业化类,如类NewCommentNotificationObject具有附加属性(评论,评论的用户)或NewFriendNotificationObject.再深入到数据库模式,然后您可以应用一种典型的ORM模式.

具体表继承(仅为完整性)

使用具体的表格可能不是一个好主意,因为它可以归结为每个通知类型单独表格(即comment_notification_objects表格,甚至更多).这不能很好地扩展,并且您将无法notification使用外键从表中引用它们.此外,您将无法使用单个查询(不使用UNION)选择一组不同类型的通知.

单表继承

单表继承只使用带有类型鉴别器列单个表.这个单表(让我们称之为notification_objects)需要包含一个type列,该列描述记录实际上是什么类型的通知(实际上你已经在你的模式中有了这个).您还需要特殊通知类型可能具有的所有属性的列(例如,auser_idcomment_id列).

   +--------------+
   | notification |
   +--------------+
   | id           |
+--| object_id    |
|  +--------------+
|
|  +-----------------------+
|  | notification_objects  |
|  +-----------------------+
+->| id PK                 |
   | date                  |
   | type                  |
   | user_id FK            |--...
   | comment_id FK         |--...
   | friend_id FK          |--...
   | [more fields to come] |
   +-----------------------+
Run Code Online (Sandbox Code Playgroud)

优点:

  1. 使用单个查询加载所有通知
  2. 使用外键保持参照完整性

缺点:

  1. 标度严重(您需要为每种通知类型添加新列)
  2. 表将被稀疏填充(许多列将为NULL)

如果您有一组中等大小且不经常更改的通知类型,我会建议您使用此架构.

类表继承

类表继承介于两者之间; 在这里,您将为notification_objects每个通知类型创建一个中央表和单独的表(例如comment_notification_object,带有id列的附加表(这是notification_object表的外键和auser_idcolumn_id:

   +--------------+
   | notification |
   +--------------+
   | id           |
+--| object_id    |
|  +--------------+
|
|  +----------------------+      +------------------------------+
|  | notification_objects |      | comment_notification_objects |
|  +----------------------+      +------------------------------+
+->| id PK                |<--+--| id PK/FK                     |
   | date                 |   |  | comment_id FK                |--...
   | type                 |   |  | user_id FK                   |--...
   +----------------------+   |  +------------------------------+
                              |
                              |  +--------------------------------+
                              |  | newfriend_notification_objects |
                              |  +--------------------------------+
                              +--| id PK/FK                       |
                                 | friend_id FK                   |--...
                                 +--------------------------------+

                                 [more TABLES to come...]
Run Code Online (Sandbox Code Playgroud)

类表继承还允许您使用单个选择查询查询所有通知.根据您需要的数据量,您需要将JOIN添加到相应的专用表中.

优点:

  1. 可以很好地扩展/添加新类型而无需修改现有结构
  2. 使用外键保持参照完整性

缺点:

  1. 当您需要的不仅仅是最小的字段集时,您需要加入专用表(可能会影响性能)

当您有许多不同的通知类型或经常扩展您的对象模型并需要定期更改/添加新的通知类型时,我会推荐此架构.

在关系框之外

您的问题明确询问了关系模式,所以我专注于此.在此框外思考时,备用解决方案可能包括:

  • Schemaless NoSQL数据库
  • 遵循发布/订阅体系结构的消息传递系统