数据库表越多越好?

时间:2009-12-03 09:22:04

标签: mysql database database-design data-modeling

最近我一直在重新思考我几个月前制作的数据库设计。主要原因是昨晚我读了vBulletin的数据库模式,看到他们使用了很多很多表。

我用于我的架构的当前“想法”,例如我的日志表,是通过使用整数区分Log的类型来将所有内容保存在一个表中:

id, type, type_id, action, message
1 ,    1,     305,      2, 'Explanation for user Ban'
2,     2,    1045,      1, 'Reason for deletion of Article'

type 1 = user, type 2 = articletype_id = the ID of the user, article or w/eaction 2 = ban, action 1 = deletion

我应该将设计更改为两个表logBanslogSomething等等吗?或者保持我目前正在使用的方法更好吗?

6 个答案:

答案 0 :(得分:7)

这里的问题是子类型。处理子类型有三种基本方法。

  1. 将每种记录类型放入一个完全独立的表中;
  2. 将记录放在父表中,然后将记录放在子类型表中;和
  3. 将所有记录放在一个表中,“可选”数据具有可为空的列(即不适用于该类型的内容)。
  4. 每种策略都有其优点。

    例如,如果不同的亚型之间几乎没有差异,则(3)特别适用。在您的情况下,如果不同的日志记录属于特定类型,那么它们是否会有额外的列?如果他们没有,或者他们把所有这些都放在一张桌子上的情况很少,那就非常有意义了。

    (2)常用于Party表。这是CRM中的常见模型,涉及父类对象,其具有人员和组织的子类型(组织也可能具有公司,协会等子类型)。人和组织具有不同的属性(例如称呼,给定名称,出生日期等等),因此将其拆分而不是使用可为空的列是有意义的。

    (2)可能更节省空间(尽管现代DBMS中NULL列的开销非常低)。更大的问题是(2)可能会让开发人员更加困惑。你会遇到某种情况,某人需要在某个地方存储一个额外的字段,并且会在该类型为空的列中将其打包,因为这样做比获得DBA添加列更容易(不,我不是在开玩笑) )。

    根据我的经验,

    (1)可能是3中最不常用的方案。

    最后,必须考虑可扩展性,这可能是(1)的最佳情况。在某些点上,JOIN不能有效扩展,您需要使用某种分区方案来减少表的大小。 (1)是这样做的一种方法(但粗略的方法)。

    但是,我不会过分担心。在成为问题之前,你通常需要获得数亿或数十亿条记录(除非你的记录真的很大,在这种情况下它会更快发生)。

答案 1 :(得分:5)

这取决于。如果您将拥有1500,000个类型1的条目和1000个类型2的条目,并且您将在类型2上执行大量查询,请将表分开。如果没有,只保留一个表更方便。

请记住可扩展性:

  • 1年内每种类型的参赛作品数量是多少?

  • 我将在这张桌子上做多少次请求?

  • 您可以在某个时候清除此日志吗?你可以把它移到另一个表(比如X个月以前的档案条目)吗?

答案 2 :(得分:2)

我现在看到的一个缺点是你不能在你的type_id上​​强制执行外键完整性,因为它指向许多不同的表。

答案 3 :(得分:1)

我想添加一个小提示。有点偏离主题,而且相当基本,但使用enum而不是tinyint来表示状态标志要清楚得多,即

   enum('user','type')

如果只有两种状态,tinyint的内存效率会更高,但不太清楚。枚举的另一个缺点是您将业务逻辑的一部分放在数据层中 - 当您需要添加或删除状态时,您必须更改数据库。否则它更清楚,我更喜欢enum

答案 4 :(得分:0)

我会尽可能保持具体的内容 - 在这种情况下,我会创建两个表。 每个表都有一个特定的目的,所以我不明白为什么要将它们组合起来。

答案 5 :(得分:-1)

我不会做vBulletin做的事情。像vBulletin这样的旧应用程序的问题在于,虽然它们可能已经开始作为精益机器,但是随着时间的推移它们会收集大量的熵并最终变得臃肿。由于有插件,第三方工具以及开发过旧代码的开发人员,因此打破它是一个艰难的选择。

这就是为什么这里没有太多的重构。不要把它们变成你的编程模型。环顾四周,找出最有效的方法并使用它。很多桌子听起来对我不好,不好。