3

我正在开发具有多租户的SaaS应用程序,并且我决定为客户端数据使用单个数据库(MySQL Innodb)。我选择使用复合主键,如PK(client_id,id)。我有2种方式在这里,复合主键和自动增量?什么是好的做法?

1:增量 “编号” 由我自己(通过触发器或代码)

2:制作 “身份证”,通过MySQL的自动递增。

在第一种情况下,我将有独特的的ID为每一个客户,所以每个客户都会有编号1,2,3等。 在第二种情况下的ID将所有客户拓展业务。 这里最好的做法是什么?我的优先级是:性能,安全&缩放。谢谢!

+1

第一个选项确实不会让你非常满意,必须予以维护。这个新表与客户表有一对多的关系吗?究竟是什么让记录显而易见?如果没有,那么使用自动增量。这实际上只取决于情况。 – sgeddes

+1

作为最后一条评论的后续,client_id是一个外键?也就是说,它是否引用客户端表中的现有ID? –

+1

你的主键应该只是自动增量编号。不要包含client_id,它不会添加其他信息。带innodb的auto_increment id的PK(client_id,id)只有在添加一个索引(id)时才可能实现,这将再次不会添加其他信息。而具有自我维护ID的PK(client_id,id)会增加开销,同时又不会添加额外信息(例如,如果您不想通过测试来检查新数据是否已存在以确保数据完整性 - 如果添加新的一行,无论如何你都会增加ID)。所以:PK(id)和一个索引(客户端)。 – Solarflare

回答

2

您一定要使用自动增量id值作为主键。碰巧有很多原因。这里有一些。

  1. 避免竞争条件(意外id重复)需要非常小心,如果你自己生成它们。花费精力开发,质量保证和操作 - 使您的SaaS非常出色,而不是在主钥匙上重新设计轮胎。
  2. 即使不是PK,您仍然可以在(client_id, id)上放置索引。
  3. 您的JOIN操作将更容易编写,测试和维护。
  4. 此查询模式非常适合从表中获取每个客户端的最新行。它表现非常好。如果您生成自己的pks,则很难做到这一点。

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

我只是认为,在客户数据之间选择时,组合键可以为我提供某种安全性(防止拼写错误的'id'等),并且可能会在未来进行某些缩放(分片)专业人员。但看起来我只是复杂的东西!) – teMkaa

1

“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会将数据集群“聚集”在一起)。