如何为用户通知去规范化MySQL数据库?

3

我认为对于用户通知来说,对数据库进行反规范化是必要的。例如,当标记一个帖子(应该被用户考虑)时,我们添加一个flag ENUM('yes', 'no')列(或状态列)。通过计算user_id='XX' AND flag='yes' WHERE子句,可以找到一个用户的标记事件。

这种规范化结构很好;但如果我们有不同类型的通知,例如帖子、评论和照片的标记……这意味着当用户只访问他的个人资料页面时,我们需要计数多个表格。 对于像StackExchange这样的跨项目来说,这更加严重,因为我们得到来自不同站点的通知。

我认为反规范化可以帮助将通知列添加到用户表中,如下所示:

post_flags tinyint(3),
comment_flags tinyint(3),
photo_flags tinyint(3),

在这种情况下,我们需要运行一个额外的写查询来更新每个相应操作上的用户标志列。例如,当标记帖子时:UPDATE users SET post_flags=post_flags+1 WHERE user_id='XX'。我的担心是确保后面的查询执行以避免该数字与标记帖子数量不匹配; 但我认为可以通过TRANSACTION来保证。
这样,我们可以通过一次查询获取所有频繁访问的个人资料页面上的所有通知。
我走对了吗?还是有其他诡计常用于此目的?

你打算在 tinyint(3) 中存储什么?难道不会有多个条目吗? - Karoly Horvath
例如,在标记帖子时,我们将运行查询“UPDATE users SET post_flags=post_flags+1 WHERE user_id='XX'”,以更新通知数量。 - Googlebot
"标记 ENUM('是', '否')" - 为什么不使用1和0的INT类型? - Ivan
枚举类型有什么问题?它们使用相同的存储大小并完成相同的任务。 - Googlebot
1
枚举不是SQL。不同的平台以不同和不兼容的方式支持它。据我所知,主流商业数据库管理系统都不支持它。MySQL和PostgreSQL以不同和不兼容的方式支持它。更改枚举需要更改模式;与外键引用相关的表的更改仅需要插入一行。8 Reasons Why MySQL's ENUM Data Type Is Evil 是相关的。 - Mike Sherrill 'Cat Recall'
3个回答

1

你最好使用用户通知表格。

create table user_notifications (
  user_id integer primary key, -- ? references users, not shown
  post_flags unsigned tinyint(3) not null default 0,
  comment_flags unsigned tinyint(3) not null default 0,
  photo_flags unsigned tinyint(3) not null default 0
);

一个单独、较窄的表既具有逻辑性,又(可能)更快。对于标志来说,使用无符号类型,因为负数在此处毫无意义,并且MySQL不强制执行CHECK约束。

就规范化而言,user_notifications 在5NF中。


设计很好,但我不确定将用户和用户通知拆分成两列是否真的有必要,因为通知可以添加到用户列中。由于它们是“tinyint”,即使有很多通知,它们在表结构中也会很小。 - Googlebot
1
任何东西都可以添加到“用户”表中。这不是问题。你应该问的问题是这些标志是否包含有关用户或其他信息。显而易见的答案是它们包含有关其他信息的信息。(有关通知的信息。)因此,从逻辑上讲,它们属于不同的表。较窄的表将允许更多的行适合一页,因此您需要从磁盘读取较少的页面-也许是很多较少的页面。这意味着“更快”。(在我的沙盒中,使用空缓存选择一行大约快1000倍-0.05毫秒与34.5毫秒相比。) - Mike Sherrill 'Cat Recall'

1

这个是否有进行反规范化?在我看来,创建这三列似乎是更好的组织方式,也更符合正常化的要求。


一个很好的例子是账户余额。查找某人的交易历史记录很繁琐,因此跟踪“余额”意味着您只需要查看一个地方。我认为你在正确的轨道上! - Luc
1
我认为这是反规范化,因为我们正在存储过多的数据! - Googlebot
嗯,说得好。我认为你的设计很好。摘要数据对用户帐户非常有用,因为需要大量查找。另一个例子是我们跟踪的个人资料访问次数。我会计算这些次数,但也将它们存储在子表中。在他们的个人资料页面上,只需获取一个整数值就可以更快地完成操作。 - Luc

0

我认为这并不是非常有效的。也许当你需要查找标志的组合时,例如post_flags OR comment_flags OR photo_flags,并且查询的顺序也很重要时,它可能是有用的。


在用户个人资料页面,我们需要展示用户所有标记的数量。这意味着,我们需要对每个表(帖子、评论、标记)进行计数查询。 - Googlebot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接