【问题标题】:Multi databases vs. composite primary key - Laravel Saas app多数据库与复合主键 - Laravel Saas 应用程序
【发布时间】:2016-04-19 15:21:11
【问题描述】:

所以。我正在构建一个多租户 Laravel SaaS Web 应用程序,在数据库设计方面有点卡住。我一直在四处寻找解决方案,但我真的无法决定选择哪一个。我真的希望你们中的一些比我更有经验和知识的人能提出一些建议。很抱歉这篇文章很长,但我希望你能坚持下去。

问题:

在应用程序中,我的用户将从他们自己的外部数据库(使用已知架构)导入数据。

例如:我将导入具有属性的产品到类别。最简单的方法是将外部 product_id 导入产品的新主键。 但是由于用户 product_id 可能会发生冲突,我必须为每个产品分配一个新的主键,同时在同步回外部数据库时仍保留外部 product_id 以供参考。

例如:外部 product_id 将是 ext_product_id,我将分配一个新的 product_id 作为主键。

到目前为止,我可以想到 3 种方法来做到这一点:

解决方案 1 - 具有新主键的单一数据库:

因此,如果我导入产品和类别列表,我将不得不将每个外部 product_id 保存为 ext_product_id 并为产品分配一个新的主键。然后,我必须查询类别 ext_category_id = products ext_category_id,然后使用新的主键 product_id 和主键 category_id 创建一个新关系。 在导入数千行时,这些循环查询需要很长时间,而且有些表有 4 种不同的关系,这意味着需要跟踪和同步大量“ext_”列。

解决方案 2 - 复合主键:

由于每个用户都不会引用外部数据库,因此我可以创建由 tenant_id 和 e.g. 组成的复合键。外部 product_id。这将允许我批量插入带有由租户组成的键前缀的外部数据。这样,关系应该“开箱即用”。 但据我所知,Laravel 不支持该功能?有什么想法吗?

解决方案 3 - 多个数据库:

为每个租户创建一个单独的数据库可能是最好的解决方案性能和理智(首先),因为我只能复制/批量插入外部数据库,并且关系将立即起作用. 但我真的很担心这种设计的可扩展性:我实际上能够管理多少个数据库?假设我有 1000 甚至 10000 个客户? 如果我想在更新中添加一列怎么办?我可以对所有数据库执行某种循环迁移吗?

我真的希望你们中的一些人可以帮助我继续前进,因为我被困住并且没有解决方案 2 和 3 的经验。

提前致谢!

【问题讨论】:

    标签: php mysql database laravel multi-tenant


    【解决方案1】:

    我个人会选择解决方案 2,因为这可能是最安全的。

    应该排除解决方案 1,因为您不想通过修改应用程序的用户来混淆他们的数据。

    解决方案 3 可能很难维护,并且更有可能失败(应用程序的后端)+ 您将失去对其数据库的所有跟踪。

    至于在我看来是理想的解决方案 2: 我不知道您使用的是什么(PHPMyAdmin 或其他类型),但基本上您想要做的是有 2 列:

    table
        id(PK, AI) original_id(PK)
    

    然后就是你桌子的其余部分。 像这样,您将拥有自己的自动增量 (AI) 密钥,并且您不会与用户发生任何冲突,因为您的 auto_increment 和用户的组合总是唯一的。

    例如:

    user1:
        id = 1 | original_id = 1
    user2:
        id = 2 | original_id = 1
    

    这仍然有效,因为组合是独一无二的。 使用这种复合 UID 的另一个优点是您仍然可以使用自己的 id 对所需的行等执行查询或操作...

    希望对你有帮助

    【讨论】:

    • 感谢您的回答!你有使用 Laravel 和复合主键的经验吗?
    【解决方案2】:

    在选择架构时需要考虑很多事情,但根据您的描述,我建议您使用解决方案 3,因为:

    • 正如您已经很好指出的那样,它是最佳的解决方案性能方面(尤其是如果您最终有很多客户)并且您不需要为所有客户处理大量条目的开销一张桌子
    • 您有一个清晰的数据库结构,其中只存在必要的关系,无需额外的麻烦来跟踪不同的客户

    就维护和更新数据库结构而言,您可以创建Laravel Commands 来自动运行多个数据库的迁移。您可以查看this answer 以了解如何做到这一点(尽管这种情况与您需要的情况略有不同,但它提供了一些见解)。此外,任何其他需要批量处理的事情都可以通过 Laravel 命令或其他脚本自动化,因此数据库的数量不应妨碍维护。

    【讨论】:

    • 非常感谢您的回答 - 我想我会选择解决方案 3。
    【解决方案3】:

    一种更现代的方法是使用 UUID 作为主键。如果你也 当您导入的数据有 source_uuid、import_time 等时,您可以在表中记录所有导入(和导出)。

    说服各方使用 UUID 可能很困难 - 但这是最​​好的方法。

    /gh

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-08
      • 1970-01-01
      • 2014-07-15
      • 2014-01-26
      • 2022-07-15
      • 2012-06-01
      • 2018-01-31
      • 2011-10-26
      相关资源
      最近更新 更多