我目前有一个由单个终端客户使用的应用程序。为便于讨论,假设应用程序只需要一个数据库表来存储所有记录。我现在需要支持多租户,因此将来我将有大约500名客户使用相同的数据库服务器。
1)可能的解决方案是为每个客户建立一个单独的数据库。因为将有大约500个客户意味着拥有MySQL / SQL Server / Oracle / etc ...托管500个独立的数据库。对于在基于云的平均服务器上运行的数据库服务器而言,这听起来有点过分了。
2)另一个解决方案是坚持使用我已有的单个数据库,但要有500个不同的表,每个最终客户一个。每个客户只在自己的表中平均大约2000条记录。这很容易实现,我猜想可以很容易地将客户迁移到另一台服务器,只需移动整个表数据。
3)最后,我可以坚持在单个数据库中使用单个表。相反,我添加了一个额外的列,用于标识记录所属的客户。但随后该表最终得到了大约1,000,000条记录,这是所有500个客户的总数,平均每个2,000个。
我对性能和缩放知之甚少,知道1,2,3会提供最佳性能。有什么想法吗?
答案 0 :(得分:3)
2,000行甚至1,000,000并不是特别大。
您需要处理的问题不是基于效果的。从性能的角度来看,您应该将所有内容放在一个表中(在您提到的所有三个数据库中)。
如果您有其他要求 - 特别是安全性或备份要求 - 那么您可能需要考虑多个表或数据库。例如,如果要单独备份每个客户端,则可能有单独的数据库。如果您有安全要求,其中 数据与其他客户端分开,那么您可以考虑使用单独的表。从性能的角度来看,正确的解决方案是将所有内容放在一个表中。
答案 1 :(得分:0)
通常,在任何数据库方案中,选项2都被视为不良设计风格。关于设计数据库的规则规定,相同类型的数据通常应存储在同一个表中(即,不要创建2个或更多表来在同一个数据库中存储相同类型的记录)
至于1到3之间的选择,它实际上归结为你想要做的事情:
为每个最终用户创建一个隔离的解决方案
从长远来看,这可能会更清洁,规模更好。它还可以帮助您处理交叉污染,以及creata有效的数据备份策略。此外,它有助于确保,如果您选择清除(丢弃)一个用户的数据,您不会意外删除其他用户的数据。
所以,我会选择1 - 每个客户一个数据库在大多数情况下更好。
为多个客户创建一个单独的解决方案,作为产品(即软件即服务)
在这种情况下,如果您确定每个客户都会生成少量数据,您可以选择将数据存储在多个客户的单个表中。但即便如此,创建多个数据库也可能会更好。但这取决于其他因素(您的预算是一个)。
从表演的角度来看,几千条记录都不算什么。即使您有几千个客户(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