500个数据库或1个数据库,500个表或只有1个表包含所有记录?

时间:2014-10-24 03:25:34

标签: mysql sql-server oracle performance scaling

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

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

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

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

我对性能和缩放知之甚少,知道1,2,3会提供最佳性能。有什么想法吗?

4 个答案:

答案 0 :(得分:3)

2,000行甚至1,000,000并不是特别大。

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

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

答案 1 :(得分:0)

通常,在任何数据库方案中,选项2都被视为不良设计风格。关于设计数据库的规则规定,相同类型的数据通常应存储在同一个表中(即,不要创建2个或更多表来在同一个数据库中存储相同类型的记录)

至于1到3之间的选择,它实际上归结为你想要做的事情:

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

    从长远来看,这可能会更清洁,规模更好。它还可以帮助您处理交叉污染,以及creata有效的数据备份策略。此外,它有助于确保,如果您选择清除(丢弃)一个用户的数据,您不会意外删除其他用户的数据。

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

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

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

  3. 从表演的角度来看,几千条记录都不算什么。即使您有几千个客户(1000 x 1000 - >数百万,或数十或数百万),只要数据被正确编入索引并且硬件是正常的(即硬件),您仍然可以使用单个数据库进行管理(即私人服务器,而不是共享服务器。但从长远来看,其他考虑因素(新功能,更多客户或更多数据)可能会证明每个客户使用数据库更有意义。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

这会给你很好的组织。并且(例如)如果您发现对单个数据库的需求太多,那么将您的大客户(即将推出)推向他们自己的数据库是一件轻而易举的事。

我"想出了"这个技巧因为我的Asp.Net托管网站为多个数据库收取了更多的钱。但是我的代码已经编写为没有遍布客户唯一ID标记。每个"客户"网站使用相同的数据库,但使用不同的模式名称。

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