Ruby on rails 为什么在联接表上有主键不好?

Ruby on rails 为什么在联接表上有主键不好?,ruby-on-rails,database,migration,primary-key,junction-table,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 a

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

本例中的联接表在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提到的,我可以理解自动编号字段作为主键的潜在用途,即使对于联接表也是如此。然而,在我上面列出的示例中,作者明确避免在“createtable”语句中创建语法为“:id=>false”的自动编号字段。通常,Rails会自动向迁移过程中创建的表中添加一个自动编号id字段,这将成为主键。但是对于这个连接表,作者特别阻止了它。我不知道他为什么决定采用这种方法。

DBA会告诉您,在这种情况下,主键实际上是两个FK列的组合。由于Rails/ActiveRecord不能很好地使用复合PKs(至少在默认情况下),这可能就是原因。

外键的组合可以是主键(称为复合主键)。就个人而言,我喜欢使用技术主键,而不是(自动编号字段、序列等)。为什么?嗯,它使识别记录变得更加容易,如果要删除它,可能需要这样做


想一想:如果你要展示一个包含所有链接的网页,用主键识别记录会更容易。

基本上是因为不需要它。两个外键字段的组合足以唯一标识任何行

但这仅仅说明了为什么这不是一个好主意。。。。但为什么这是个坏主意呢

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


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

在任何表、句点(如果DBMS是关系型DBMS或SQL DBMS)上不使用主键是个坏主意。主键是数据库完整性的关键部分

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

一些注意事项:

  • category_id和post_id的组合本身是唯一的,因此额外的id列是多余和浪费的
  • “拥有主键不好”这句话在屏幕广播中是不正确的。您仍然有一个主键——它只是由两列组成(例如,CREATE TABLE foo(cid,pid,Primary Key(cid,pid))。对于习惯于在任何地方附加ID值的人来说,这可能看起来很奇怪,但在关系理论中,这是非常正确和自然的;剧本作者最好说是这样“将名为'ID'的隐式整数属性作为主键并不好”
  • 有额外的列是多余的,因为您将在category_id和post_id的组合上放置唯一的索引,以确保不会插入重复的行
  • 最后,虽然常用术语称之为“复合键”,但这也是多余的。关系理论中的术语“键”实际上是唯一标识行的零个或多个属性的集合,因此可以说主键是category_id,post_id
  • 将最具选择性的列放在主键声明的第一位。关于b(+/*)树构造的讨论超出了本答案的范围(有关一些较低级别的讨论,请参阅:)但在您的情况下,您可能希望它出现在post_id、category_id上,因为post_id在表中的显示频率较低,从而使索引更有用。当然,由于表很小,而且索引本质上是数据行,所以这不是很重要。在更广泛的情况下,表会更宽

  • 单一主键的优点

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

    • 使用更多的磁盘空间
    • 需要3个索引而不是1个
    • 如果没有唯一的约束,您可能会得到同一关系的多行
    注释

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

    将最有选择性的列放在第一位应该只与索引声明相关。在键声明中,它应该无关紧要(因为,正如已经正确指出的,键是一个集合,在集合中,顺序并不重要-集合{a1,a2}与{a2,a1}是相同的集合)

    如果一个DBMS产品的键声明中属性的顺序不同,那么该DBMS产品就是因为没有正确区分数据库的逻辑设计(执行键声明的部分)和数据库的物理设计(执行索引声明的部分).

    我想对