【问题标题】:Composite Primary Keys and auto increment? What is a good practices?复合主键和自动增量?什么是好的做法?
【发布时间】:2016-09-15 07:14:37
【问题描述】:

我正在开发具有多租户的 SaaS 应用程序,并且我决定使用单个数据库(现在是 MySQL Innodb)来存储客户的数据。我选择使用像 PK(client_id, id) 这样的复合主键。我这里有两种方法,

1:自己增加“id”(通过触发器或代码)

2:将“id”设为mysql自增。

在第一种情况下,我将为每个客户端拥有唯一的 id,因此每个客户端都有 id 1、2、3 等。 在第二种情况下,所有客户的 id 都会增长。 这里的最佳做法是什么?我的优先事项是:性能、安全性和可扩展性。谢谢!

【问题讨论】:

  • 第一个选项对你的帮助并不大,必须维护。这个新表会与客户表有一对多的关系吗?究竟是什么让这张唱片与众不同?如果没有,则使用自动增量。这真的取决于情况。
  • 作为最后一条评论的后续,client_id 是外键吗?也就是说,它是否引用了客户端表中的现有 id?
  • 您的主键应该只是自动递增的 id。不要包含 client_id,它不会添加任何其他信息。 PK(client_id, id) with auto_increment id for innodb 只有在添加 index(id) 时才有可能,这将再次添加任何其他信息。并且具有自维护 id 的 PK(client_id, id) 将增加开销,同时再次添加任何其他信息(例如,您不想通过测试 id 是否已存在以确保数据完整性来检查新数据插入 - 如果您添加新行,无论如何你只会增加 id)。所以:PK(id) 和一个索引(Client)。
  • 是的,与客户表的关系是一对多,client_id 是引用客户表中现有 id 的外键!

标签: mysql database-design relational-database database-schema saas


【解决方案1】:

您肯定希望使用自动递增的id 值作为主键。发生这种情况的原因有很多。这里有一些。

  1. 如果您自己生成竞争条件(意外id 重复),则需要非常小心。将精力(开发、质量检查、运营)花在让您的 SaaS 变得出色上,而不是在主键上重新发明瘪胎。
  2. 即使不是 PK,您仍然可以在 (client_id, id) 上添加索引。
  3. 您的JOIN 操作将更易于编写、测试和维护。
  4. 此查询模式非常适合从表中获取每个客户端的最新行。它表现得非常好。如果你自己生成 pk,这种事情就更难做到了。

        SELECT t.*
          FROM table t
          JOIN (SELECT MAX(id) id 
                  FROM table 
                 GROUP BY client_id
              ) m ON t.id = m.id
    

【讨论】:

  • 我只是想,在选择客户端数据时,复合键会给我某种安全性(防止拼写错误的 'id' 等),将来可能还会有一些缩放(分片)专家.但看起来我只是把事情复杂化了!)
【解决方案2】:

"PK(client_id, id)" --

id INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY(client_id, id),
INDEX(id)

是的,这种组合会起作用。它将有效地工作。它不会为每个客户端分配 1,2,3,但这无关紧要。相反,连续的 id 将分散在客户端中。

可能您的所有查询都包括WHERE client_id = (constant),对吗?这意味着将始终使用PRIMARY KEY(client_id, id),而不会使用INDEX(id),除非满足AUTO_INCREMENT

此外,PK 将比拥有INDEX(client_id, id) 更有效。 (这是因为 InnoDB 将 PK 与数据“聚集”在一起。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    • 2011-09-25
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    相关资源
    最近更新 更多