更简单的查询与更简单的数据库

时间:2012-11-27 20:10:50

标签: database database-design

在我的网站上,我有一个论坛,您可以在该论坛中启动帖子,回复帖子,删除帖子,报告其他人的帖子等。

我决定进行抽象并创建一个名为activity的表,该表将存储user_idtime(每个活动共有的字段)以及活动类型(线程,响应,报告,删除)和effective_id(与各个表对应的id)。

一开始这似乎是一个好主意,因为它有助于避免冗余,并且可以更容易查找某个用户所做的事情,而无需询问每个表格。但与此同时,这种抽象会导致更复杂的查询(例如,几乎每个简单查询都必须使用INNER JOIN),现在我遇到了更复杂的查询问题。

所以我的问题是:我做出了正确的决定吗?即使在导致非常昂贵的查询的情况下,在真实环境中拥有一个完美的数据库是如此重要吗?

4 个答案:

答案 0 :(得分:1)

关系数据库系统的关键在于关联数据(通过在正确的表中分离实体),这样就可以引入连接。这是正常的,也是一种很好的数据库设计技术。

许多数据库初学者试图避免连接并从各种实体添加属性以避免必须进行INNER连接,但这不是一种正确的技术,并且从长远来看会让你感到困惑。联接是有原因的,应该在需要关联数据时使用。

在您的示例中,您实质上是在创建“日志”文件。应用程序上的活动只是记录用户正在执行的操作。问问自己,什么是更好的帖子日志,报告日志,删除日志,日志,此外还有许多日志表或一个带有referenceID的简单日志表,关于用户发起的活动(这个实际上是FK)。答案是你想要一个包含外键的日志表,包含用户发起的内容(删除,添加,标记等)。

您想问自己的问题是,当用户只想获取此数据时,为什么要显示活动信息。您可以随时将此数据标准化,但只在需要时选择它。我不明白你为什么要加入这个活动表。

答案 1 :(得分:1)

我想我会像你3 - 5年前那样走向同一个方向,但现在我更倾向于为你所描述的活动设计一个更简单,更平坦的数据库设计,而不是采用更规范化的方法。

我对CQRS和任务驱动UI的使用和理解确实帮助我实现了这一点 - 尽管它可能与您的情况无关。

本质上,我曾经优化过我的数据库,因此插入,更新和删除非常有效,但这会导致连接许多表以进行简单的选择。问题是80%的时间,用户想要选择。因此,在大多数情况下优化用户所做的数据库结构确实有助于提高应用程序的整体性能,并且在我看来,系统的维护和可扩展性也是如此。

我对你的应用程序以及你想要做的事情做了一些假设,但对我来说,一个活动表听起来像是可以从队列中提供并由一个单独的工作进程/线程构建的监视工作项的队列。当找到这些工作项(命令??)时,工作进程将展平数据并更新相应的活动表。当你去查询你的活动表时,你基本上是在做一个简单的SELECT * FROM ACTIVITY(虽然我不建议SELECT *个查询 - 命名你的列。因此,您可以轻松插入/更新活动表,但您的选择性能非常好。

我希望这会有所帮助。

答案 2 :(得分:1)

我不确定你的问题是什么,你的目的是分割所有活动的共同特征,以及复杂查询给你带来麻烦的方式。

活动类型(线程,响应,报告,删除)的描述当然看起来像是类型和子类型的经典案例,也称为类和子类。这种情况有两种经典的设计模式,称为单表继承和类表继承。这两种设计模式有标签。还有另一种设计模式,共享主键,可以与类表继承一起使用,效果很好。

从STI到CTI的转变确实涉及一些表分解,它与您描述的分解类似。 SPK的使用消除了对每个专用子类表的单独id字段的需要,并且还消除了对单独的类型字段的需要。这可能会导致查询比您最终挣扎的查询更简单。没有看到这些疑问,就不可能知道。

值得注意的是,这种分解不是"标准化"从获得符合任何标准正常形式2NF到5NF的意义上讲。但是这些正常形式关注的是更新的简单性,而不是简单的查询。

考虑到数据的使用方式,可以进行良好的设计。有时我们会一路走来。我不知道完美的设计是什么样的。我认为我们总是在权衡利弊。

答案 3 :(得分:0)

您是否考虑过对数据库进行非规范化?请点击此处了解更多信息:http://en.wikipedia.org/wiki/Denormalization