在这种情况下,代理键是否比自然键更好

Son*_*ngo 5 performance index database-design best-practices primary-key

我从这里复制了这段代码:

CREATE TABLE records(
    email TEXT REFERENCES users(email),
    lat DECIMAL,
    lon DECIMAL,
    depth TEXT,
    upload_date TIMESTAMP,
    comment TEXT,
    PRIMARY KEY (upload_date,email)
);

CREATE TABLE samples(
    date_taken TIMESTAMP,
    temp DECIMAL,
    intensity DECIMAL,
    upload_date TIMESTAMP,
    email TEXT,
    PRIMARY KEY(date_taken,upload_date,email),
    FOREIGN KEY (upload_date,email) REFERENCES records(upload_date,email)
);
Run Code Online (Sandbox Code Playgroud)

引起我注意的第一件事是使用自然复合键作为两个表的主键。

我能够从这段代码中提取 3 件事:

  1. users表(此处未显示)email用作text..类型的主键。
  2. records表使用复合键text+ timestamp
  3. samples表使用 3 个类型为text+ timestamp+ 的字段的复合键timestamp

现在在这种情况下,代理键不是更好的识别吗?我的意思是性能明智的索引 anint应该比索引 a 更好text?有什么东西会使代理键成为一个糟糕的选择吗?

HLG*_*GEM 11

对于任何 PK,无论是复合的还是单一的,电子邮件都是一个特别糟糕的选择。请参阅我在 Stack Overflow 上对这个问题的回答,了解原因:

/sf/ask/266287591/#3804174

  • @Songo - 某些“代码表”值,尤其是那些由标准机构确定的值,可以是合理的自然键。想想性别的“M”或“F”,以及货币和国家/地区代码之类的东西。否则,代理键通常更安全、更好。 (3认同)

Bil*_*hor 6

我会考虑两个因素:

  • 主键值不应更改或重复使用。电子邮件地址往往会发生变化。我通常使用代理作为数据库中的用户 ID。
  • 当长字符串不是索引中的第一个字段时,它们往往会破坏索引键压缩。根据数据的聚合方式,这可以通过将电子邮件地址移动到索引中的第一个字段来解决。

使用更好地代表电子邮件地址所代表的概念的代理键可能是更好的解决方案。也许像contributer_id 这样的字段可能是更好的字段。可能需要将电子邮件地址转换为该字段的附加表。

编辑:我已经重新审视了你的设计。您可能需要查看建模采样事件(位置和所用时间)、样本和电子邮件地址。Samples 将是采样事件的子级。采样事件的代理键可能适用于采样事件表,以在将键迁移到子表时限制键中的列数。

我不知道你在抽样什么以及它是如何聚合的。设计时应考虑数据需要如何聚合。