【问题标题】:Do I need a primary key if something will NOT be changed?如果某些内容不会更改,我是否需要主键?
【发布时间】:2010-12-31 22:41:12
【问题描述】:

如果我有一个用户可以标记另一个用户帖子并且无法撤消或更改的网站,我是否需要主键?我所有的选择都在 post_id 上,并带有 where 子句来查看用户是否已经标记了它。

【问题讨论】:

  • 这不是同一个问题。
  • 其实是同一个问题。唯一的区别是你在上面加上了具体的情况。
  • "All my selects would be on the post_id and with a where clause to see if the user already flagged it." 现在这就是您所需要的。当您需要查看有多少用户标记了帖子时会发生什么?单个用户标记了多少帖子?该数据还有其他用途,您不认为 KEY 会更有帮助。如果您有大量记录,即使针对 post_id 和 user_id 进行搜索也会大大加快速度。

标签: sql database-design data-modeling


【解决方案1】:

您不需要主键,即使用户要修改行也是如此。但是,每次查询该表时,主键都会优化性能。如果您认为您的表会增长到大约一千行左右,那么设置主键将显着提升性能。

不创建主键的唯一好处是它意味着你不必创建一个,我想这很公平:-P

你现在不能打扰创建一个。您以后可以随时添加。没什么大不了的。不要让任何人欺负你认为你现在绝对必须创建一个主键!你很快就会看到它非常慢:-P 然后你可以在那个时候添加主键。如果到那时你没有太多重复:-P

【讨论】:

  • 会不会占用几个字节?在这种情况下,我看不出 PK 如何提高速度
【解决方案2】:

主键与是否可以更改数据无关 - 它是整行的单一参考点,可以更快地查找和/或更改数据。

我的所有选择都在 post_id 上,并带有 where 子句以查看用户是否已标记它。

您需要提供有关业务规则的更多信息。例如,系统是否应支持多个用户标记同一帖子?

如果答案是“否”,那么我会为 POST_STATUS_CODE 表建模,并在 POSTS 表中为该表设置一个外键。

如果答案是“是”,那么我仍然有一个 POST_STATUS_CODE 表,还有一个链接 POSTSPOST_STATUS_CODE 表的表 - 比如 POSTS_STATUS_XREF

我有一个 post_flag 表,其中包含 post_id、user_id(标记它的人)和 flag_type(ATM 作为一个字节)。在这种情况下,我看不出 PK 如何让它更快,但我想它每行会占用 4 或 8 个字节。我正在考虑索引 post_id。如果我这样做了,我还应该创建一个 PK 吗?

至少,我会将主键设置为以下组合:

  • post_id
  • user_id

原因是主键确保不能重复。

主键可以由多个列组成 - 这称为复合键。这意味着这对值是唯一的。 IE:1, 1 值的组合不能超过一个,但可以有 1,21,3 等(反之亦然)。尝试添加重复项将导致重复主键错误。

【讨论】:

  • 我有一个 post_flag 表,其中包含 post_id、user_id(标记它的人)和 flag_type(ATM 为字节)。在这种情况下,我看不出 PK 如何让它更快,但我想它每行会占用 4 或 8 个字节。我正在考虑索引 post_id。如果我这样做了,我还应该创建一个 PK 吗?
  • 编辑。凉爽的。 “至少,我会让主键成为组合”你所说的组合是什么意思?如果我有一个 PK 我可以插入 post_id 和 user_id 并且不需要检查相同的条目是否已经存在? (这是拥有它的充分理由,但我打算写一个 where 语句以确保它不存在)
【解决方案3】:

从您的其他一些帖子看来,您试图避免向表中添加主键的原因是为了节省空间。

别这么想了。

在没有先测试它们是否真的有效的情况下进行这样的非标准优化是个坏主意。您是否运行了一些测试,表明您通过省略该表的主键在数据库中节省了大量空间?还是你只是在猜测?

使用主键并不一定意味着您将使用更多空间。根据数据库,如果您省略主键,它可能会为您添加一个隐藏字段(例如,如果您在 MySQL/InnoDB 中没有 PK,它会在包含 6 字节行 ID 的合成列上添加一个隐藏的聚集索引值 (source))。如果您确实使用主键,而不是添加新列,您只需选择一些您知道无论如何都应该是唯一的现有列。它不会占用更多空间,只是意味着数据将以不同的顺序存储,以便于搜索。

当您添加索引时,该索引会占用额外的空间,因为索引基本上只是表中几列的副本,加上指向原始表中行的链接。还记得当您没有 PK 时数据库使用的隐藏列吗?那么现在它必须使用它来查找您的行,因此您也会在索引中获得它的副本。如果您使用主键,那么您可能不需要已添加的索引之一,因此您实际上在这里节省了空间。

除此之外,如果您的表上没有主键,一些有用的数据库工具将无法正常工作。在您离开后,您会惹恼所有必须维护您的数据库的人。

那么告诉我,为什么你认为没有一个是个好主意?

【讨论】:

  • 很好的答案。补充一点,我想说他的主键实际上是通过 M:N 表的 user_id + post_id 。通过对 2 个 FK 进行索引,在任一方向上的查找都将非常快。那么问题就变成了,性能还是空间?在当今的计算中,哪一项真正会让您付出最大的代价?
【解决方案4】:

阅读:"Is it OK not to use a Primary Key When I don’t Need one?"

是的,您确实需要一个主键。

如果你认为你不这样做,你也可以使用文本文件来存储,因为这意味着你不理解它们......

【讨论】:

    【解决方案5】:

    软件要求可能会迅速变化。客户可能会提出新的要求。因此,拥有主键可能很有用,因为您可以在这种情况下完全消除不必要的数据迁移。

    【讨论】:

      【解决方案6】:

      主键有助于加快查找和连接,所以如果可以的话,拥有它总是很好的。

      【讨论】:

        【解决方案7】:

        在这种情况下,你可能不用一个主键就可以逃脱,但无论如何我都倾向于在那里放一个主键,只是因为这样做相对简单,并且如果需求发生变化可以节省返工。

        【讨论】:

          【解决方案8】:

          简单的答案是肯定的。每个表都应该有一个主键(至少由一列组成)。没有一个有什么好处?

          【讨论】:

            【解决方案9】:

            最好有一个,如果只是因为您可能不得不手动删除偶尔的记录(例如重复),并且一个应该有一个唯一的标识符。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-05-15
              • 1970-01-01
              • 2018-04-25
              • 2012-05-01
              • 1970-01-01
              • 2012-05-04
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多