【问题标题】:Table with only one column or add a numeric primary key?只有一列的表或添加数字主键?
【发布时间】:2012-11-25 13:10:37
【问题描述】:

假设我需要一个包含帐户 ID 且没有其他信息的简单表。有两种方法可以做到:

id varchar(255) PRIMARY KEY

或添加数字主键:

id int PRIMARY KEY
accountId varchar(255) UNIQUE NOT NULL

这两种方法的优点/缺点是什么?你会选择哪一种?为什么?

第一个解决方案对可维护性(如果我们需要更改单行的 id 怎么办)和性能有什么影响?

【问题讨论】:

  • 在第一种情况下,Id 不可为空。在第二种情况下 accountId is 可以为空。也许不是你想要的?指定 NOT NULL 以使其清楚。
  • @sqlvogel 我确实指定了 NOT NULL 以使其清楚。
  • 嗯,您的意思是您将其添加到问题中,从而使我的回答实际上毫无用处。

标签: mysql database database-design schema


【解决方案1】:

如果该列的内容是唯一的(这似乎是 ID 的情况),那么继续并使其成为主键, 否则创建另一个数字列作为主键。

问候,

【讨论】:

    【解决方案2】:

    不同之处在于 PRIMARY KEY 约束暗示/强制执行 NOT NULL CONSTRAINT。在第一个示例中,varchar(255) 将有效提升为 varchar(255) NOT NULL

    DROP SCHEMA tmp CASCADE;
    CREATE SCHEMA tmp ;
    SET search_path=tmp;
    
    CREATE TABLE pk
            ( id varchar(255) PRIMARY KEY
            );
    
    CREATE TABLE uniq
            ( id int PRIMARY KEY
            , accountid varchar(255) UNIQUE
            );
    
    INSERT INTO pk (id) VALUES(NULL);
    INSERT INTO uniq (id, accountid) VALUES(1, NULL);
    

    结果:

    DROP SCHEMA
    CREATE SCHEMA
    SET
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "pk_pkey" for table "pk"
    CREATE TABLE
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "uniq_pkey" for table "uniq"
    NOTICE:  CREATE TABLE / UNIQUE will create implicit index "uniq_accountid_key" for table "uniq"
    CREATE TABLE
    ERROR:  null value in column "id" violates not-null constraint
    INSERT 0 1
    

    由于 PK (-->>NOT NULL) 约束,第一次插入失败;第二个成功了。

    【讨论】:

      【解决方案3】:

      这归结为数据库世界中代理键与自然键的争论。有关该主题的文本,请参见例如 here、here 和 here。我认为这两种选择都是有效的,但在这种情况下,我会选择 AccountID 作为自然键(假设 AccountID 对于每个帐户都是唯一的,不会为空,也不会发生变化),因为这意味着更少的开销。在这种情况下,我看不到代理键的附加值。

      自然键:

      • 对用户有意义
      • 在需要时很难更改
      • 可能会导致在查询中需要更少的连接

      代理键:

      • 对用户没有任何意义
      • 不会发生变化
      • 可能导致在查询中需要更多连接
      • 可能需要额外或更大的索引

      【讨论】:

      • 优秀的答案。我没有意识到问题实际上是关于代理键的。另一个问题是其他表可能有指向此 PK 的 FK。除了“稳定键”问题之外,它还意味着所有引用表都需要一个 varchar(255) 来引用我们。
      • 如果自然键永远不会改变怎么办?那么使用自然键会更好吗?
      • 很好的答案,但我不同意 “可能需要额外或更大的索引” 部分。在“自然键”情况下而不是在“代理键”(索引可能是4 或 8 个字节宽)。
      • 如果自然键永远不会改变,我会说使用它。但是@wildplasser 提出了一个很好的观点:varchar(255) 列类型是一个相当大的列,可以用作键。如果此列在许多其他表中被引用,则代理可能会更好。
      • @ypercube 我猜他的意思是你不能只用代理键替换自然键。代理键通常必须与自然键同时存在,这意味着一个额外索引(因此索引大小的总和会增加)。话虽如此,如果您的访问路径主要是通过代理,那么代理的较小索引肯定有其优势...
      猜你喜欢
      • 1970-01-01
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      相关资源
      最近更新 更多