Stack Exchange的数据库架构是否遵循良好实践?

时间:2014-08-08 15:46:09

标签: sql database database-design relational-database database-schema

这是一个元问题,但因为它与数据库设计有关,我想我应该在这里发布。

我正在构建一个包含Q + A的网站,并且想知道我应该如何构建我的SQL数据库,所以很自然地,我查看了best of the best。但是,Stack Exchange数据库架构似乎无视what I've learned创建可维护/可扩展的表层次结构。

Stack Exchange's database schema for posts, as shown in the data explorer

正如您所看到的,Stack Exchange会存储其所有"帖子"在一个表中,除了注释,它有自己的表。帖子类型包括问题,答案和各种维基。这导致表中有很多NULL列。例如,问题有标题,标签和answerCounts,而答案不是,所以所有答案条目对所有这三列都有NULL。如果随着时间的推移添加更多的帖子类型,这将逐渐变得不易维护。而评论是唯一具有自己的表的帖子类型似乎不一致。

我所阅读的内容表明,它通常更倾向于使用对象子类层次结构,其中有一个通用的"帖子"表格以及每种类型帖子的一堆表格,这些表格都有一列映射回"帖子"表。这样可以将空列的数量保持在最小值并使其更具可扩展性,但会降低查询速度,因为它们需要更多连接。

那么为什么Stack Exchange会使用这种巨大的表格方法呢?这只是对旧数据库进行修改的结果吗?更具体地说,我应该将此模型用于我自己的Q + A系统还是坚持使用对象子类层次结构(我的Q + A /论坛系统将非常类似于SO,包括问题,答案,民意调查等几种类型的帖子,评论等)?

1 个答案:

答案 0 :(得分:4)

这是所谓“Object-relational impedance mismatch”的经典案例。具体来说,您正在将OO的继承映射到关系数据库结构。有几种常见的方法 -

  • 每个子类的表格,
  • 每个叶子类的表,
  • 每个类层次结构的表(带有鉴别器)

这些策略中的每一个都是完全有效的。此外,可以根据需要混合结构。

看起来Stack Exchange使用每个类层次结构方法的表,PostTypeId用作鉴别器。这种方法与他们可能采取的任何其他方法一样有效。从维护的角度来看,它也是最简单的方法之一,因为它可以让您以较少的工作量构建手动查询。

在表的结构中还有另一件事你没有提到:它没有标准化。具体来说,有AnswerCountCommentCount字段存储可以通过聚合表获得的信息(即运行SELECT COUNT(*) FROM ... WHERE ... AND other.ParentId = p.Id ...)这是标准化和执行速度之间的常见权衡:大多数可能,分析表明聚合需要花费大量时间,因此计数已移至“父”记录中。