【问题标题】:Two columns as primary key OR one column as PK + index?两列作为主键或一列作为PK +索引?
【发布时间】:2012-08-21 07:23:08
【问题描述】:

此表格包含用户的照片(缩略图和完整照片)。
大多数查询都会有一个“WHERE user_id =?”条件。

CREATE TABLE photos (
  "photo_id" serial, -- serial is postgres' autoincrement
  "user_id" integer not null, -- foreign key to users table
  "filename_thumbnail_50" varchar not null,
  "filename_thumbnail_75" varchar not null, -- 75px x 75px thumbnail
  "filename_full" varchar not null,
  PRIMARY KEY ("photo_id", "user_id")
);

此用例的最佳设计和/或性能设计是什么:
- 两列主键,如上例?
- 一个主键 (photo_id) 和 user_id 上的索引?

【问题讨论】:

  • 您拥有的两列主键实际上没有任何意义恕我直言。不应该是(photo_id) 还是(user_id, filename)
  • 对不起,我已经更新了我的例子,所以有点复杂
  • 对于表中的每一行,每一列的值都应该依赖于“键,整个键,只有键”。 “依赖于”表示“正确的值由...标识”在序列列中添加user_id会破坏第二部分;您的表格不会处于第二范式,并且会受到相关异常的影响。请参阅任何有关关系数据库规范化的书籍或文章。
  • 一个键是一个最小的超键——一组应该是不可约唯一的属性。唯一性约束是强制执行该规则的原因。从您的问题来看,您似乎不了解您的要求( photo_id 本身是否旨在唯一?)或者您不了解密钥。

标签: sql database postgresql primary-key normalization


【解决方案1】:

主键应遵循您的业务规则,仅此而已。由于这样的照片没有“真实”(即自然)主键,因此使用序列作为 PK 绝对有意义。

user_id 扩展主键没有任何意义,也没有任何目的(因为photo_id 无论如何都是唯一的,你只会增加索引维护的开销)。由于user_id 是索引中的第二列,因此它不太可能用于限制user_id 的查询(并非不可能,但不太可能)

所以我会坚持使用photo_id 上的PK 并在user_id 上添加一个索引(无论如何,索引外键列总是一个好主意)。

【讨论】:

  • 感谢您的解释,我应该了解更多关于索引的知识。
  • @younes0:我强烈推荐这个网站:use-the-index-luke.com 它非常适合解释索引的工作原理。
【解决方案2】:

写的主键不能用于按 user_id 搜索,因为 user_id 是键中的第二列。

您的第二个选项是最好的 - 只有 photo_id 上的主键,因为这是记录的唯一标识符,并为您的查询添加一个单独的 user_id 索引。

【讨论】:

    【解决方案3】:

    如果您有自增 ID,我认为您不需要将 user_id 作为主键。你为什么不在 user_id 上使用外键到你的用户表(我猜你有一个)?

    【讨论】:

      【解决方案4】:

      如果您有一个专门用于识别目的的列(在本例中为 photo_id),则不需要第二个键列。

      如果您的情况可能有多个具有相同 photo_id 和不同 user_id 的记录,那么我认为最好有一个中间表来创建多对多关系并保留单个主键。例如:

      CREATE TABLE photos (
        "photo_id" serial, 
        -- other columns
        PRIMARY KEY ("photo_id")
      );
      
      CREATE TABLE users (
        "user_id" serial, 
        -- other columns
        PRIMARY KEY ("user_id")
      );
      
      CREATE TABLE photos_users (
        "photo_user_id" serial, 
        "photo_id" integer, -- not sure if this datatype is correct for postgres
        "user_id" integer, -- not sure if this datatype is correct for postgres
        PRIMARY KEY ("photo_user_id")
      );
      

      据我所知 - 如果所讨论的表没有特定的 id 列,并且如果只使用 1 个键,则需要第二个键列。下面是一个例子:

      CREATE TABLE Person (
          "FirstName" varchar NOT NULL,
          "LastName" varchar NOT NULL,
          "PostalCode" varchar NOT NULL,
          PRIMARY KEY ("FirstName", "LastName", "PostalCode")
      );
      

      在上述情况下,FirstName 的唯一性不足以作为主键,FirstNameLastName 也不会,因此在这种情况下至少会使用 3 列。当然,最好有一个IDPersonID 列并将其用作主键。

      就性能而言,主键不会产生太大影响。担心索引。确保将在WHERE 子句或JOINAGGREGATE 中使用的任何列都有索引。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-29
        • 2014-07-16
        • 1970-01-01
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-22
        相关资源
        最近更新 更多