【问题标题】:Database: Multiple tables or just one table?数据库:多张表还是只有一张表?
【发布时间】:2011-03-14 11:43:13
【问题描述】:

For example 我有photosvideos 表,我可以评论这些,但是当我将它发送到数据库时,哪种方式更好?

  1. 为 cmets 提供 2 个表: photo_commentsvideo_comments

  2. 或者有 1 个表 comments 和 在表格内创建一行,例如 type 如果是 photo_commentvideo_comment

我认为1 更快,因为当我需要查询表时数据较少,但2 可能更易于使用。

请告诉我什么是最好的方法,速度对我来说非常重要。

我说的是一个非常大的系统,有数百万个数据,数百万个 cmets,所以我想要最快的方法来获得结果,对我来说,是否需要编写更多代码或需要记住一点,结果更重要!

【问题讨论】:

  • 还值得指出的是,“最快”并不是一个足够好的设计标准。您必须指定您打算如何获取这些行。这是 OLTP 系统还是 OLAP 系统?您通常一次加载这些记录还是经常扫描整个表?
  • @CIRK:这与您的查询模式或用例无关。
  • Do you usually load these records one at a time or do you often scan whole tables? 我认为实时是这个问题的答案。
  • +1 表示好的和经常讨论的问题。

标签: database performance database-design comments


【解决方案1】:

拆分表在性能方面会更好,因为您不必查询额外的“评论类型”列。以这种方式做事的缺点是不能重用代码(可能在将来,如果您将 cmets 添加到其他事物中)。但听起来你并不关心这个。

【讨论】:

  • 嗯,不错的答案,但是我想我以后可以将 cmets 添加到其他东西中,因为我可以创建一个新表,这并不难:P,但我的问题很笼统,我会在这方面做很多事情方式:)
【解决方案2】:

为什么不只有一个评论表?对视频或照片的评论之间有什么区别吗?如果不是,您应该只拥有一个包含评论指向的视频/照片的外键的列,以及一个类型为 ENUM 的附加列,该列包含评论所针对的资源类型的信息。

使用ENUM 将使您的查询速度非常快(因为它被保存为一个数字),并且可以轻松地在您的查询中使用字符串。

【讨论】:

  • 我要一张表的原因:当您扩展评论系统时,我们对列进行更改,您只需更改一张表。即使这张表变得非常大,如果您正确使用索引,它也会非常快地获得视频/照片的结果。我有超过 2000 万个条目的表,并且对它们的搜索仍然非常快(即使对于非常复杂的搜索也不到 100 毫秒),所以在这种情况下,大小应该不是问题。而且你可以随时对你的表进行分区。
  • 嗯,我想我将长度/值字段留空。
  • 您的 ENUM 建议对于性能来说不是一个好的建议。使用具有此现有表结构的一个表的建议对于维护和执行引用完整性也不是一个好的建议。
  • 使用 INT 可能会快一点,但您必须记录哪个数字代表哪种类型。如果实现工作正确,RI 应该不是问题。与仅一张表相比,维护 10 个评论表怎么样?如果所有的 cmets 都具有相同的结构,那么改进二只有一个表在哪里?如果它是一个坏主意,为什么像博客软件这样的系统只使用一个表?
  • @Kau:您不能创建从两个表到一个表的外键约束。使用一个表没有任何问题,但如果你要这样做,你必须使用超类型/子类型模式正确规范化数据库(见我的回答)。说 RI“不应该成为问题”作为对糟糕设计的防御是一个危险信号。
【解决方案3】:

我认为选择为 cmets 使用 1 个还是 2 个表不会对您的应用程序的性能产生任何明显的影响。

您应该选择在您的应用程序上下文中更有意义的任何一个。

例如,如果照片上的 cmets 和视频上的 cmets 都将以相同的方式运行,那么您应该有一张桌子,但是(例如)视频上的 cmets 允许是照片上的 cmets 的两倍,或者照片上的 cmets 有一个额外的“排名”字段或其他东西,那么 2 个表会更有意义。

【讨论】:

  • 在每种类型的内容上,cmets 都是相同的,但我问这个问题是因为我想确定哪个更快,我会有很多 cmets 速度问题。
【解决方案4】:

这更多地取决于照片和视频的结构。考虑以下数据库设计:

MediaType
----------
ID *
Name

Media
----------
ID *
TypeID
OwnerName
Name
Size
Path

Photo
----------
MediaID *
MediaTypeID (constraint, always set to the photo type)
Height
Width

Video
---------
MediaID *
MediaTypeID (constraint, always set to the video type)
Rating

如果 Photo 和 Video 都具有 MediaType 和 Media 的 FK,我会让 Comments 与 Media 表相关而不是其中任何一个,而不是直接与 Photos 或 Videos 表相关。当照片和视频有很多共同属性时,这通常是我使用的设计类型。当您想要做诸如安全性之类的事情时,它特别有用,因为您不会被限制在您正在处理的每种媒体上重复相同的可见性和所有权结构。查询也非常快,因为许多查询通常只查找公共属性,或者只查找特定类型的行,因此不需要包含某些表。通过对这些 IS-A 关系建模来设计数据库还可以使您的索引保持高度选择性,这意味着 速度

如果您被锁定在您的设计中并且视频和照片没有共同的“基表”,那么我将为每个创建一个单独的 cmets 表。

【讨论】:

  • 有趣的方式,我以前从未见过:)
  • 我还想确保 MediaTypeID 具有非常小的 PK。我经常使用 TINYINT 或 CHAR(1) 来保持索引大小紧凑。请注意,MediaID、MediaTypeID 应创建为 composite 外键。
  • 您需要媒体表做什么。它绝对没用,需要另一个加入才能获得媒体的名称。
  • 媒体用于公共属性。因为我不知道他的数据库设计,所以我把 Name 留在了那里。这是实现与关系数据库的 IS-A 关系的经典且公认的方式。通常,您开始注意到照片和视频表的大多数属性实际上是通用的。在大多数情况下,父表(例如 Media)通常会成为您查询的“主”表。
  • @DaveMarkle 如果我还需要设计数据库结构,您愿意使用通用媒体表创建照片和视频吗?在我看来,加入表查询有点矫枉过正
【解决方案5】:

您的查询看起来像

select * from comments where linked_id = 555

select * from comments where linked_id = 555 and comment_type = 1

(comment type=1 表示这是一个视频)。

只要将comment type作为索引,基本上就一样快了。

我唯一会考虑的是列。如果视频 cmets 与图片 cmets 具有不同的 cmets 集,则将它们拆分。如果一切都一样,那就把它们放在一起。

【讨论】:

    【解决方案6】:

    如果你真的有两个单独的数据表photosvideos,我也总是会选择使用两个单独的 cmets 表。

    为什么?

    如果您将所有 cmets 放入一个 comments 表中,但从两个单独的数据表中引用媒体,则无法轻松地在 cmets 表和两个数据表之间设置引用完整性。有一些解决方法(比如有两个单独的参考字段,每个参考字段一个),但没有一个真的非常引人注目。没有参照完整性最终会导致不属于任何现有媒体条目的“僵尸”数据。

    拥有两个 cmets 表可以让每个评论表正确引用其关联的数据表,因此您在数据库中的数据完整性会更好。

    因此,如果您有两个单独的数据表,我总是会选择使用两个单独的 cmets 表。

    【讨论】:

    • 我不会只有photosvideos,我也会有其他的东西,所以为了让所有东西都成为comment,嗯,我不知道,还有评论呢厘米?我也应该为这些创建表格?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    • 2012-04-04
    • 2014-01-31
    • 2014-05-13
    • 2012-11-28
    • 1970-01-01
    相关资源
    最近更新 更多