为什么在连接表上有主键是不好的?

时间:2009-05-19 01:02:26

标签: ruby-on-rails database migration primary-key junction-table

我正在观看一个截屏视频,作者说在连接表上有一个主键是不好的,但没有解释原因。

示例中的连接表在Rails迁移中定义了两个列,并且作者为每个列添加了索引但没有主键。

为什么在这个例子中有一个主键是不好的?

create_table :categories_posts, :id => false do |t|
  t.column :category_id, :integer, :null => false
  t.column :post_id, :integer, :null => false
end
add_index :categories_posts, :category_id
add_index :categories_posts, :post_id
编辑:正如我在Cletus中所提到的,即使对于连接表,我也能理解自动编号字段作为主键的潜在用途。但是,在上面列出的示例中,作者明确避免在“create table”语句中使用语法“:id => false”创建自动编号字段。通常,Rails会自动将一个auto-number id字段添加到像这样的迁移中创建的表中,这将成为主键。但是对于这个连接表,作者专门阻止了它。我不确定他为什么决定采用这种方法。

8 个答案:

答案 0 :(得分:46)

一些注意事项:

  1. category_id和post_id的组合本身就是唯一的,因此额外的ID列是多余且浪费的
  2. 截屏视频中的短语“不好主键”是不正确的。你仍然有一个主键 - 它只是由两列组成(例如CREATE TABLE foo(cid,pid,PRIMARY KEY(cid,pid))。对于习惯于在任何地方添加ID值的人来说,这似乎是奇怪但在关系理论中它是非常正确和自然的;屏幕截播作者最好说“将一个名为'ID'的隐式整数属性作为主键”并不好。
  3. 拥有额外的列是多余的,因为无论如何都要在category_id和post_id的组合上放置唯一索引,以确保不会插入重复的行
  4. 最后,虽然通常的命名法称其为“复合键”,但这也是多余的。关系理论中的术语“关键”实际上是唯一标识行的零个或多个属性的集合,因此可以说主键是category_id,post_id
  5. 将MOST SELECTIVE列FIRST放入主键声明中。讨论b(+ / *)树的构造超出了这个答案的范围(对于一些较低级别的讨论,参见:http://www.akadia.com/services/ora_index_selectivity.html)但在你的情况下,你可能想要它在post_id上, category_id因为post_id将在表中较少出现,从而使索引更有用。当然,由于表太小而且索引本质上是数据行,因此这不是很重要。在更广泛的情况下,表格会更宽。

答案 1 :(得分:3)

DBA会告诉您,在这种情况下,主键实际上是两个FK列的组合。由于Rails / ActiveRecord与复合PK不兼容(默认情况下,至少),这可能是原因。

答案 2 :(得分:3)

外键的组合可以是主键(称为复合主键)。我个人赞成使用技术主键而不是(自动编号字段,序列等)。为什么?好吧,它使 更容易识别记录,如果您要删除它,可能需要这样做。

考虑一下:如果你要展示一个包含所有链接的网页,那么拥有一个识别记录的主键可以更容易。

答案 3 :(得分:3)

基本上因为没有必要。两个外键字段的组合足以唯一地标识任何行。

但这仅仅说明为什么它不是一个好主意......但为什么它会是一个坏主意呢?

考虑添加标识列的开销。该表占用的磁盘空间增加了50%。指数情况更糟糕。使用标识字段,您必须保持标识计数以及第二个索引。您将使磁盘空间增加三倍,并使每个插件上需要执行的工作增加三倍。唯一的优点是DELETE命令中的WHERE子句略短。

另一方面,如果复合键字段是整个表,则索引可以是表。

答案 4 :(得分:3)

不要在任何表上使用主键,这是一个坏主意(如果DBMS是关系DBMS - 或SQL DBMS)。主键是数据库完整性的关键部分。

我想如果你不介意你的数据库不准确并且经常提供不正确的答案,那么你可以没有......但是大多数人都希望从他们的DBMS得到准确的答案,对于这些人来说,主键是至关重要的。

答案 5 :(得分:2)

首先放置最具选择性的列只应与INDEX声明相关。在KEY声明中,它应该无关紧要(因为正如已经正确指出的那样,KEY是一个SET,并且在一个集合中,顺序无关紧要 - 集合{a1,a2}与{a2的集合相同中,a1})。

如果DBMS产品使得KEY声明中的属性排序有所不同,那么该DBMS产品无法正确区分数据库的逻辑设计(您进行KEY声明的部分)和数据库的物理设计(您进行INDEX声明的部分)。

答案 6 :(得分:2)

我想评论以下评论:“说零或更多是不正确的。”

我想说的是,添加此评论的文本根本不包含“零或更多”的文本,因此我想评论的评论的作者批评其他人没有做过的事情。说。

我还想评论说不正确说“零或更多”是不正确的。今天在少数仍然懒得研究该理论细节的人中众所周知的关系理论实际上需要一个没有属性的密钥的可能性。

但是,当我按下“评论”按钮时,系统回应我评论需要50分(或某些此类)的声誉评分。

一个悲惨的例子说明世界似乎忘记了科学不是民主,而在科学中,真理不是由碰巧成为大多数的人决定的,也不是由碰巧拥有“足够声誉”的人决定的。 / p>

答案 7 :(得分:1)

拥有单一PK的优点

  • 使用单个值
  • 唯一标识一行
  • 如果需要,可以轻松地从其他地方引用关系
  • 有些工具希望您拥有单个整数值pk

有一个PK的缺点

  • 使用更多磁盘空间
  • 需要3个索引而不是1个
  • 如果没有唯一约束,您最终可能会为同一关系设置多行

备注

  • 如果要避免重复,则需要定义唯一约束
  • 在我看来,如果你的桌子会很大,请不要使用单个pk,否则为了方便而牺牲一些磁盘空间。是的,这很浪费,但在实际应用程序中,谁在乎磁盘上的几MB。