【问题标题】:What is the advantage of using composite primary key instead of single primary key in this context?在这种情况下使用复合主键而不是单个主键有什么好处?
【发布时间】:2015-07-08 12:09:07
【问题描述】:

Cakephp v3 现在能够支持复合主键。 http://book.cakephp.org/3.0/en/quickstart.html

快速入门指南中给出的一个示例;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    created DATETIME,
    modified DATETIME
);

CREATE TABLE bookmarks (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(50),
    description TEXT,
    url TEXT,
    created DATETIME,
    modified DATETIME,
    FOREIGN KEY user_key (user_id) REFERENCES users(id)
);

CREATE TABLE tags (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    created DATETIME,
    modified DATETIME,
    UNIQUE KEY (title)
);

CREATE TABLE bookmarks_tags (
    bookmark_id INT NOT NULL,
    tag_id INT NOT NULL,
    PRIMARY KEY (bookmark_id, tag_id),
    INDEX tag_idx (tag_id, bookmark_id),
    FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
    FOREIGN KEY bookmark_key(bookmark_id) REFERENCES bookmarks(id)
);

快速入门指南提到"You may have noticed that the bookmarks_tags table used a composite primary key. CakePHP supports composite primary keys almost everywhere, **making it easier to build multi-tenanted applications**."

多租户应用程序是什么意思?在这种情况下,为什么使用复合主键比使用单一主键更好?

【问题讨论】:

  • 最好在某些地方使用复合主键而不是到处使用。如您所见,我们在这里不需要任何其他主键,并且如果组合起来,两个键本身都可以用作主键,因此最好在此处使用复合主键。
  • 几乎在所有地方都支持复合主键,使得构建多租户应用程序变得更加容易应该阅读让它可能 构建关系数据库 是否已租用。关系键是复合键,就这么简单。如果你没有关系键,你就没有关系数据库、关系完整性、能力或速度......你有一个记录归档系统。

标签: mysql cakephp database-design primary-key composite-primary-key


【解决方案1】:

简而言之:clustering

InnoDB 将自动对具有相同 bookmark_idbookmarks_tags 行进行集群(物理分组),使某些查询1 非常快,因为 DBMS 不必在整个表中“跳跃”收集所有相关的行。

在这种情况下,不需要代理键(自动增量 int),也不需要您为其基础索引支付的额外价格。有关自然键与代理键的更深入讨论,请查看here

虽然我不熟悉 Cakephp v3,但我猜它们只是意味着您可以在所有表​​的键前加上租户 ID,并且由于集群而在性能方面付出的代价很小。


1 如:“查找给定书签的标签”。而且由于您在{tag_id, bookmark_id} 上也有索引,因此相反的查询:“查找给定标签的书签”也会很快。

【讨论】:

  • @user768421 这通常是性能问题,但在某些情况下也可能需要正确性 - 请参阅第二个链接中的“菱形依赖项”。即使在这种情况下,您也必须拥有复合键以避免多次对同一个书签使用相同的标签。唯一的问题是您是否需要一个代理键 - 在这种情况下似乎回答“否”。
  • @user768421 而且您似乎很幸运地使用了一种不会强制您使用代理键的工具,因此您可以使用更多的键设计适用于每个特定情况。
  • 那个Surrogate Key标签wiki很困惑(a)代理不是“key”,它只是一个代理(它没有在*RM中定义Key,并且它没有键的任何属性)(b)在任何表层次结构中,您都需要它来实现基本的关系完整性,而不仅仅是“菱形”表! (c) 复合密钥的主要优点是完整性 (d) 在关系范式中没有“超级密钥”之类的东西,它是批评者的捏造。
  • @Branko Dimitrijevic。 (a) 所有无法在 cmets 中回答的问题。请打开一个新问题。 RM 可以在线获得 (b) 我已经写了很多次了,只是谷歌。 (c) 显然你相信主观的“真理”。我珍视客观真理。前一场辩论。对于后者,无需争论。
  • @Branko Dimitrijevic。你正在失去我。你说你同意,但你正在做相反的事情。我再说一遍,我不辩论,我站在证据上。辩论 30 年前已解决的问题的人拒绝提供证据。我没有私人定义,我对工程定义很满意。 RM 表示 E F Codd 博士的 关系模型,而不是其他作者写的垃圾。也许是聊天会话。
【解决方案2】:

多租户 将多个不同组织的数据保存在同一个数据库中,但其数据在逻辑上彼此分离。对于有许多客户使用一个通用应用程序的系统提供商来说,这是一种常用方法。

您引用的 CakePHP 文档中的注释的意义在于,他们希望您通过在每个表的主键中添加类似 org_id 的内容来将多个组织(租户)的数据隔离在一组表中。

当然,在单用户系统的上下文中使用复合主键还有其他原因,但显然 CakePHP 在添加此功能时考虑到了多租户支持。

【讨论】:

    【解决方案3】:

    如果我们做select * from bookmarks_tags,那么排序将在表bookmarks_tagsbookmarks_id(first field)列的基础上进行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 2022-01-23
      • 1970-01-01
      相关资源
      最近更新 更多