【问题标题】:500 databases or 1 database with 500 tables or just 1 table with all the records? [closed]500 个数据库或 1 个包含 500 个表的数据库,还是只有 1 个包含所有记录的表? [关闭]
【发布时间】:2014-12-19 21:11:43
【问题描述】:

我目前有一个供单个最终客户使用的应用程序。为了便于讨论,假设应用程序只需要一个用于所有记录的数据库表。我现在需要支持多租户,因此将来我将有大约 500 个客户使用同一数据库服务器。

1) 一种可能的解决方案是为每个客户建立一个单独的数据库。由于将有大约 500 个客户,这意味着拥有 MySQL/SQL Server/Oracle/etc... 托管 500 个单独的数据库。对于在普通云服务器上运行的数据库服务器来说,这听起来有点过头了。

2) 另一种解决方案是坚持使用我已经拥有的单一数据库,但要拥有 500 个不同的表,每个最终客户一个。每个客户在他们自己的表中平均只有大约 2000 条记录。这很容易实现,我猜想可以很容易地将客户迁移到另一台服务器,只需将整个表数据移动过来。

3) 最后,我可以坚持在单个数据库中使用单个表。相反,我添加了一个附加列来标识记录所属的客户。但随后该表以大约 1,000,000 条记录结束,这是所有 500 个客户的总和,每个客户平均有 2,000 个。

我对性能和扩展了解不够,无法知道 1、2、3 将提供最佳性能。有什么想法吗?

【问题讨论】:

标签: mysql sql-server oracle performance scaling


【解决方案1】:

2000 行甚至 1000000 行都不是特别大。

您需要处理的问题不是基于性能的。从性能的角度来看,您应该将所有内容放在一个表中(在您提到的所有三个数据库中)。

如果您有其他要求——尤其是安全或备份要求——那么您可能需要考虑多个表或数据库。例如,如果您分别备份每个客户端,那么您可能有单独的数据库。如果您有数据必须与其他客户端分开的安全要求,那么您可以考虑单独的表。从性能的角度来看,正确的解决方案是将所有内容放在一个表中。

【讨论】:

  • 一百万行是微小的。 25 年前它还很小——Foxpro 因成为第一个不具备此功能的数据库而闻名。今天,如果程序员有点能干,低端服务器在处理十亿行的行时没有问题。
【解决方案2】:

一般来说,选项 2 在任何数据库场景中都被认为是糟糕的设计风格。设计数据库有一条规则,即同类型的数据一般应该存储在同一个表中(即不要创建 2 个或多个表来存储同类型的记录在同一个数据库中)

至于 1 和 3 之间的选择,这真的归结为您要做什么:

  1. 为每个最终用户创建一个独立的解决方案

    从长远来看,这可能会更干净,规模更大。它还将帮助您处理交叉污染,并为数据创建有效的备份策略。此外,它有助于确保,如果您选择清除(丢弃)某个用户的数据,您不会意外删除其他用户的数据。

    所以,我会选择选项 1 - 每个客户端一个数据库在大多数情况下会更好。

  2. 创建您为多个客户维护的单一解决方案,作为产品(即软件即服务)

    在这种情况下,如果您确定每个客户都会生成少量数据,您可以选择将数据存储在一个表中以供多个客户使用。但即使在那里,创建多个数据库可能会更好。然而,这取决于其他因素(您的预算是其中之一)。

从性能的角度来看,几千条记录不算什么。即使您有几千个客户(1000 x 1000 -> 数百万,或数千万或数百万),只要数据被正确索引并且硬件是半体面的(即。私人服务器,而不是共享服务器)。但从长远来看,其他考虑因素(新功能、更多客户或更多数据)可能会证明使用每个客户的数据库更有意义。

【讨论】:

【解决方案3】:

我肯定会为 500 个客户使用一张表,您的应用程序逻辑应该能够确保每个客户只能看到正确的数据。您描述的卷非常小,但即使是非常大的卷也可以通过使用优化的 SQL 并由高效的主键和索引支持来快速检索。

【讨论】:

    【解决方案4】:

    在 Sql Server 中,我将为每个客户创建一个 SCHEMA...并托管 Customer001Schema 下的所有表,然后是 Customer002Schema 等。

    这将为您提供出色的组织。并且(例如)如果您发现对单个数据库的需求过多,则可以轻而易举地将最大的客户(未来)推送到他们自己的数据库中。

    我“想出了”这个技巧,因为我的 Asp.Net 托管站点对多个数据库收取了更多的费用。但是我的代码已经被编写为没有客户唯一标识标签。每个“客户”网站都使用相同的数据库,但架构名称不同。

    Sql Server 中的 SqlCmd 模式使得创建脚本相当容易。

    http://msdn.microsoft.com/en-us/library/ms174187.aspx

    http://msdn.microsoft.com/en-us/library/ms162773.aspx

    示例:

    :setvar MySchemaName "Customer001"
    
    if not exists(select 1 from information_schema.schemata where schema_name='$(MySchemaName)')
    BEGIN
        EXEC ('CREATE SCHEMA $(MySchemaName) AUTHORIZATION dbo;')
    END
    
    GO
    
    IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'$(MySchemaName)' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' ) 
    BEGIN 
    DROP TABLE [$(MySchemaName)].[Employee] 
    END 
    GO
    
    
    CREATE TABLE [$(MySchemaName)].[Employee] ( 
    
        [EmployeeUUID] [uniqueidentifier] NOT NULL,
        [ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
        [TheVersionProperty] [timestamp] NOT NULL,
        [SSN] [nvarchar](11) NOT NULL,
        [LastName] [varchar](64) NOT NULL,
        [FirstName] [varchar](64) NOT NULL,
        [CreateDate] [datetime] NOT NULL,
        [HireDate] [datetime] NOT NULL
        )
    
    GO
    

    【讨论】:

    • 请注意,我参与了 2 个项目,这些项目不得不在同一个数据库中艰难地分离多个“客户”数据......残酷的工作。因为早期决定将所有数据放在同一个数据库和模式中。 100 次中有 99 次,我认为将其分开将是有益的....对于“未来”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多