我正在帮助一个 Rails 应用程序,目的是让该应用程序成为多租户。这意味着数据库表中将有来自多个用户/组织的数据,并且访问路径通常是“为我的组织获取所有数据”。
我们使用 MYSQL 作为数据库。
默认情况下,Rails 使用 id 列在表上创建一个主键。id 列是自动递增的。这在某些方面很好 - 行总是添加到表的末尾。但是,请考虑以下情况:
- 一个名为 foo 的对象。foo 有一个 id,并且总是有一个 organization_id
- 随着时间的推移,每个组织都会在数据库中创建 foo,这些 foo 在整个表中交错(它们存储在 id 序列中)
- 涉及列出该组织的所有 foo 的用例
我遇到的问题是,一个组织的 foo 在数据库中的位置并不紧密,实际上它们的分布非常不理想。理想情况下,我会在表上创建 (organisation_id, id) 的主键,这将导致给定组织的所有 foo 并排在表中。
不幸的是,当我这样做时,Rails 给了我一个“模型 Foo 中表 foos 的未知主键”错误。我想我可以通过使用组合键 gem to rails 来解决这个问题,但似乎应该有某种方法可以在数据库级别使其透明。
有替代方法吗?
作为参考,数据库上更改我的索引的命令是:
ALTER TABLE foos ADD KEY (id); # 需要,因为 id 列是自动递增的
ALTER TABLE foos DROP PRIMARY KEY, ADD PRIMARY KEY(organisation_id, id);
编辑 1:一篇博文,表明使用 Composite_primary_keys gem 做到了这一点。这让我对这种方法更有信心,问题是它是从 2008 年开始的,所以事情可能已经发生了变化。 http://www.joehruska.com/?p=6
编辑 2:我正在考虑的另一个选择是分区 - 组织的数量可能不会超过最大分区,我可能可以将它们分组一点而不会失去太多好处。不幸的是,键引用是表上的每个唯一键都必须使用表的分区表达式中的每一列。(这还包括表的主键- 来自 MYSQL 手册http://dev.mysql.com/doc/refman/5.6/en/partitioning-limitations-partitioning-keys-unique-keys.html。
所以我仍然需要再次使用复合主键。我有点惊讶 Rails 如此关心主键,而不仅仅是存在一个键。