我正在建立一个 SaaS 系统,我们计划为每个客户提供自己的数据库。该系统已经设置好,因此如果负载变得太大,我们可以轻松地扩展到其他服务器;我们希望有成千上万的客户,甚至数以万计的客户。
问题
- 您可以/应该在一台 SQL Server 上拥有的微数据库数量是否有任何实际限制?
- 它会影响服务器的性能吗?
- 拥有 10,000 个每个 100 MB 的数据库,还是一个 1 TB 的数据库更好?
附加信息
当我说“微型数据库”时,我并不是指“微型”;我的意思是我们的目标是成千上万的客户,所以每个单独的数据库只占总数据存储的千分之一或更少。实际上,每个数据库都在 100MB 左右,具体取决于它的使用量。
使用 10,000 个数据库的主要原因是为了可扩展性。事实上,V1 系统有一个数据库,当数据库在负载下紧张时,我们有过一些不舒服的时刻。
它使 CPU、内存、I/O 紧张——以上所有。尽管我们解决了这些问题,但它们让我们意识到,在某些时候,即使拥有世界上最好的索引,如果我们像我们希望的那样成功,我们根本无法将所有数据放在一个大本营' 数据库。所以对于 V2,我们正在分片,所以我们可以在多个数据库服务器之间分配负载。
去年我一直在开发这个分片解决方案。它是每台服务器一个许可证,但无论如何,由于我们在 Azure 上使用虚拟机,因此已经处理好了。现在出现这个问题的原因是因为以前我们只向大型机构提供服务并自己设置每个机构。我们的下一个业务订单是自助服务模式,任何拥有浏览器的人都可以注册并创建自己的数据库。他们的数据库将比大型机构小得多,数量也多得多。
我们尝试了 Azure SQL 数据库弹性池。性能非常令人失望,因此我们切换回常规 VM。
我曾在单个实例上使用 8 到 10,000 个数据库的 SQL Server 工作。这不漂亮。
重新启动服务器可能需要一个小时或更长时间。想想 10,000 个数据库的恢复过程。
您不能使用 SQL Server Management Studio 在对象资源管理器中可靠地定位数据库。
备份是一场噩梦,因为要使备份有价值,您需要有一个可行的灾难恢复解决方案。希望您的团队擅长编写一切脚本。
你开始做一些事情,比如用数字命名数据库,比如
M01022
和T9945
。试图确保您在正确的数据库中工作,例如,M001022
而不是M01022
,可能会令人抓狂。为这么多数据库分配内存可能会非常痛苦。SQL Server 最终会执行大量 I/O,这可能会真正拖累性能。考虑一个记录 10,000 家公司的 4 个表中的碳使用详细信息的系统。如果你在一个数据库中这样做,你只需要 4 个表;如果您在 10,000 个数据库中执行此操作,那么您突然需要在内存中存储 40,000 个表。在内存中处理这么多表的开销是巨大的。如果有 10,000 个数据库正在使用,则您设计的任何将针对这些表运行的查询都需要计划缓存中的至少10,000 个计划。
上面的列表只是您在以这种规模运行时需要计划的问题的一小部分。
您可能会遇到诸如 SQL Server 服务需要很长时间才能启动的问题,这可能会导致服务控制器错误。可以自己增加服务启动时间,创建如下注册表项:
例如,要在服务超时前等待 600 秒(10 分钟),请键入 600000。
自从写下我的答案后,我意识到问题是在谈论 Azure。也许在 Azure SQL 数据库上执行此操作不是那么成问题;也许问题更大。就个人而言,我可能会设计一个使用单个数据库的系统,可能会在多个服务器上垂直分片,但肯定不是每个客户一个数据库。
所以这两种方法各有利弊。在不了解您的应用程序或您希望提供的服务的更多信息的情况下,我将无法给出明确的答案,但我会就此事发表一些想法。
我为什么应该为所有客户端使用 1 个数据库的理由。
优点
易于维护。拥有一个数据库意味着您只需在一个位置而不是多个位置执行维护任务。想象一下处理 1000 个不同的数据库进行备份的噩梦。更新 1000 个数据库的统计信息或重建索引
DBCC CHECKDB
怎么样?部署代码。假设您的应用程序代码或报告中的存储过程存在问题。您需要进行快速更改...现在您必须将该更改部署到 1000 多个数据库。不,谢谢,我宁愿不要。
容易的可见性。想象一下 SSMS 试图打开 1000 多个数据库(不寒而栗)。它实际上会使问题变得毫无用处,并且需要花费大量时间来打开和呈现 SSMS。请记住,前提是您能够提出一个体面的命名约定。
缺点
安全。如果您将其他客户数据作为单独的数据库,则防止人们查看其他客户数据会更容易。但是,您可以做一些非常简单的事情来防止这种情况发生。
表现。有人可能会说,将每个客户限制为一个数据库意味着 SQL 服务器将不得不扫描更少的数据来获取您正在查询的信息。但是,通过正确的数据结构和良好的索引(以及可能的分区),如果仔细完成,您可能会完全消除这个问题。我建议为每个包含客户特定数据的表提供某种引导
CompanyID
以减少开销。最终,我认为最好的选择是为您的应用程序拥有一个数据库,并在数据库本身内拆分客户数据。与管理 1000 多个数据库的噩梦相比,它给您带来的麻烦将微不足道。
SQL Server 的最大容量规范指出限制为 32,767。
至于它是否会影响性能,答案是肯定的,但它影响性能的方式,以及是否会影响性能,将取决于无数因素。
除非有充分的理由将其拆分为 10,000 个数据库,否则我会选择一个数据库。一个备份还是 10,000 个备份?一次完整性检查,还是 10,000 次?使用 10,000 个小型数据库可能有充分的理由,但您没有提供足够的细节来确定这一点。您提出的问题非常广泛,没有足够的信息让任何人知道最佳答案是什么。
您在这里谈论的是多租户与多实例架构。我只是提出这些术语,因为你没有在你的问题中使用它们,但这就是你所讨论的,如果你只是将“多租户架构”插入谷歌,你会发现大量的资源和讨论关于它,整本书都写在上面。
这里有一些关于 SQL Server 的好资源:
https://msdn.microsoft.com/en-us/library/ff966499.aspx
https://learn.microsoft.com/en-us/azure/sql-database/sql-database-design-patterns-multi-tenancy-saas-applications
我会同意其他答案,因为我强烈倾向于默认使用多租户,除非您有令人信服的理由支持多实例。
您不需要拆分成数千个单独的客户端数据库来扩展,还有许多其他方法可以做到这一点,这可能更可取。像集群、复制、分片、分区等。不要重新发明轮子。没有什么固有的说您需要在单个客户级别上手动拆分它,并且确实这样做可能会显着增加添加每个新客户的成本。
您在谈论“数百万”客户,将任何基于云的大型软件视为服务,Gmail 等等,您几乎不会认为他们为每个新注册创建一个全新的数据库,现在是吗?
您确实希望促进这一点的原因可能是,例如,如果您将产品销售给必须将其托管在他们自己的基础架构上的客户。但作为一般的 SAAS 规则,默认采用多租户架构。
我可以看到单数据库建议的缺点之一是与回滚数据有关 - 如果您为每个租户设置了一个数据库,您可以独立地恢复每个客户的数据(并恢复到特定的时间点)。如果它们都在一个数据库中,这将变得更加困难(并且更容易出错,因为它可能需要通过 INSERT/UPDATE/DELETE 语句来完成)。
感谢所有回答的人-非常感谢您给我考虑的要点。我的总体感觉是单个数据库更可取,但我想补充一些反对分片架构的观点,并解决其他人提到的一些问题。
分片的动机
正如(更新的)问题中提到的,我们的目标是在全球范围内实现大规模销售,拥有数百万用户。凭借世界上最好的硬件和索引,单个数据库服务器不会承担负载,因此我们必须能够跨多个服务器进行分布。而且,一旦您必须查找任何给定客户的数据在哪台服务器上,给他们一个专用数据库就没有太多工作要做,这使得事情在保持人们的数据整齐隔离方面变得更简单。
对担忧的回应
如果您认为我遗漏了什么,我将很高兴在评论中收到您的回复!