我正在建立一个SaaS系统,我们打算在该系统中为每个客户提供他们自己的数据库。系统已经设置好,如果负载太大,我们可以轻松地扩展到其他服务器。我们希望拥有成千上万甚至数万个客户。
问题

在一个SQL Server上可以/应该拥有的微数据库数量是否有实际限制
会影响服务器的性能吗?
拥有10,000个每个100 MB的数据库或一个1 TB的数据库更好吗?

其他信息
当我说“微数据库”时,我并不是真的意思是“微”。我只是说我们的目标是成千上万的客户,因此每个单独的数据库仅占总数据存储量的千分之一或更少。实际上,每个数据库的容量大约为100MB,这取决于它获得的使用量。
使用10,000个数据库的主要原因是为了实现可伸缩性。事实是,系统的V1有一个数据库,当DB承受负载时,我们经历了一些不舒服的时刻。即使我们解决了这些问题,他们也使我们意识到,即使在世界上索引率最高的情况下,如果我们如希望的那样成功,我们也无法将所有数据都放在一个巨大的鸿沟中的数据库。因此,对于V2,我们正在分片,以便我们可以在多个数据库服务器之间分配负载。
我去年已经开发了这种分片解决方案。这是每台服务器一个许可证,但是由于我们在Azure上使用VM,因此无论如何都要注意。之所以出现这个问题,是因为以前我们只向大型机构提供服务,并且自己建立每个机构。我们的下一个业务流程是自助服务模型,任何使用浏览器的人都可以注册并创建自己的数据库。与大型机构相比,他们的数据库将更小,数量更多。
我们尝试了Azure SQL数据库弹性池。性能非常令人失望,因此我们切换回常规VM。

#1 楼

我曾在单个实例上使用8至1万个数据库的SQL Server上工作。不好看

重新启动服务器可能需要一个小时或更长时间。考虑一下10,000个数据库的恢复过程。

您不能使用SQL Server Management Studio在对象资源管理器中可靠地定位数据库。

备份是一场噩梦,因为要使备份有价值,您需要适当的灾难恢复解决方案。希望您的团队擅长于编写所有脚本。尝试确保您在正确的数据库中工作,例如用M01022代替T9945可能会令人发疯。 SQL Server最终需要进行大量的I / O操作,这可能会严重影响性能。考虑一个在10,000个公司的4个表中记录碳使用详细信息的系统。如果在一个数据库中执行此操作,则只需要4个表;如果在10,000个数据库中执行此操作,突然间您将需要40,000个表。处理该数量的表在内存中的开销是巨大的。如果正在使用10,000个数据库,则您针对这些表运行的任何查询设计都将需要至少10,000个计划在计划缓存中。您需要为以这种规模的操作进行计划。您可以自己增加服务启动时间,创建以下注册表项:例如,要在服务超时之前等待600秒(10分钟),请键入600000.


自编写答案以来,我已经意识到问题在谈论Azure。也许在SQL数据库上执行此操作不是那么麻烦。也许这更成问题。就个人而言,我可能会设计一个使用单个数据库的系统,也许是在多个服务器之间垂直分片,但肯定不是每个客户一个数据库。

评论


好东西。发布者可能会考虑使用多个数据库的方法,但是每个数据库使用多个客户,这样他们可以限制数据库的数量,但仍然可以扩展到多个服务器。

–托尼·欣克尔(Tony Hinkle)
17年8月29日在18:55

我目前正在管理一个实例,该实例的数据库计数高到4位,并且可以回显几乎所有这些信息。以这种规模进行操作时出现的另一个问题是无法长时间缓存执行计划。结果是大量的CPU烧录重新编译查询计划。

– alroc
17年8月31日在12:50

#2 楼

因此,这两种方法都有优点和缺点。在不了解有关您的应用程序或要提供的服务的更多信息的情况下,我将无法给出确切的答案,但我会就此事提出一些想法。为所有客户端使用1个数据库。
专业人士


易于维护。拥有一个数据库意味着您只需要在一个位置上执行维护任务,而无需在多个位置上执行。想象一下处理1000个不同数据库进行备份的噩梦。如何更新1000个DB的统计信息或重建索引或DBCC CHECKDB


部署代码。假设您在应用程序代码或报表中的存储过程有问题。您需要进行快速更改...现在,您必须将该更改部署到1000多个DB。不,谢谢,我宁愿不这样做。


可见性很容易。只需想象一下SSMS尝试打开1000多个DB(抖动)。实际上,该问题将变得毫无用处,并且仅花费很长时间才能打开并呈现SSMS。请记住,这就是您能够提出一个体面的命名约定的原因。

缺点



安全性。如果您将其他客户数据作为单独的数据库,则可以防止人们查看其他客户数据。但是,您可以执行一些非常简单的操作来防止这种情况发生。


性能。可以争辩说,每个客户将数据库限制为一个数据库意味着SQL Server将不得不扫描较少的数据以获取您要查询的信息。但是,如果使用适当的数据结构和良好的索引编制(以及可能的分区),则可以将其作为一个问题而彻底消除,如果仔细进行的话。我建议给包含客户特定数据的每个表某种形式的前导CompanyID,以减少开销。


最终,我认为最好的选择是为您的应用程序使用一个数据库,然后在数据库本身内部拆分客户数据。与管理1000多个数据库的噩梦相比,它给您带来的麻烦将荡然无存。

#3 楼

SQL Server的最大容量规范指出最大限制为32,767。关于是否会影响性能,答案是肯定的,但是它会影响性能的方式以及是否会影响性能,这取决于多种因素。

除非有充分的理由将其拆分为10,000个数据库,否则我会选择一个数据库。一个备份还是10,000个备份?一份完整性检查,还是一万张?使用10,000个小型数据库可能有充分的理由,但是您没有给出足够的详细信息来确定这一点。您提出的问题范围很广,没有足够的信息让任何人知道最佳答案是什么。

#4 楼

您在这里谈论的是多租户与多实例架构。我只是提出这些术语,因为您没有在问题中使用它们,但这就是您正在讨论的术语,如果您将“多租户体系结构”插入Google,则会发现大量资源和讨论关于它,整本书都写在上面。库/ff966499.aspx

https://docs.microsoft.com/zh-cn/azure/sql-database/sql-database-design-patterns-multi-tenancy-saas-applications

我会有其他答案,因为我会强烈倾向于默认多租户,除非您有令人信服的理由支持多实例。

您不会需要将其拆分为成千上万个单独的客户端数据库以进行扩展,还有许多其他方式可能更可取。像集群,复制,分片,分区等。不要重新发明轮子。没有内在的含义表明您需要在单个客户级别上手动进行拆分,并且确实这样做可能会显着增加添加每个新客户的成本。客户,想到任何大型的基于云的软件即服务,Gmail,无论如何,您几乎都不会认为他们为每次新注册都创建了一个全新的数据库,对吧?例如,如果您要将产品销售给必须在自己的基础架构上内部托管的客户,则可以在此方便。但是作为一般的SAAS规则,默认情况下,精简为多租户体系结构。

#5 楼

对于单一数据库建议,我可以看到的缺点之一是回滚数据-如果您为每个租户设置了一个数据库,则可以独立地还原每个客户端的数据(并还原到特定时间点)。如果它们全部都在一个数据库中,这将变得更加困难(并且更容易出错,因为很可能需要通过INSERT / UPDATE / DELETE语句来完成此操作)。

评论


+1-这是每个租户拥有一个数据库的极少数极好的好处之一。

– Max Vernon♦
18年5月10日在18:47

#6 楼

感谢所有回答-非常感谢您给我的思考要点。我的总体感觉是,最好使用单个数据库,但是我想添加一些抵消点,以支持分片架构,并解决其他人提到的一些担忧。

动机用于分片

(已更新的问题)中提到,我们的目标是在全球范围内实现数百万用户的大规模销售。凭借世界上最好的硬件和索引,单个数据库服务器将不会承担任何负载,因此我们必须能够在多个服务器之间进行分配。而且,一旦您必须查找任何给定客户的数据在哪台服务器上,为他们提供专用数据库就不需要做太多工作了,这使得在保持人们的数据整齐隔离方面变得更加简单。有关问题



重新启动服务器需要很长时间:可以,但是在正常操作中,我们不打算重新启动任何服务器。该系统最终必须全天候24/7联机,因此,如果我们要安排停机时间,则无论如何都必须对其进行计划。一切。没问题。

命名数据库/在SSMS中定位它们:命名约定很容易,仅基于客户名称即可。如果名称共享,请添加序列号。

维护:如果每个数据库都像我想象的那么小,则无需手动重建索引。

部署代码:我们使用实体框架,因此每一个架构更改将自动发布到具有新版本的每个数据库中。但是,确实可以发现,如果我们发现生产中的性能问题可以通过简单的索引调整来解决,那么将其推出就不是那么容易。另一方面,由于每个数据库都这么小,因此生产碎片上不太可能出现顶级性能问题。通用数据库仍然是一个单独的数据库,这些关注点不适用。 >

评论


如果您正在寻找24/7的正常运行时间,则需要研究如何对数据库进行集群。仅应用补丁程序将至少导致一些停机时间。不确定如何将其应用于基于云的解决方案(例如Azure),希望它能为您解决。

–杰伊·泽洛斯(Jay Zelos)
17年8月31日在10:29

我相信,使用当今的数据库技术,几乎所有“分片”的理由都不再成立。我相信您要么会后悔,要么甚至可能不会意识到自己相对较差,因此不会因无知而后悔。我同意马克斯的回答,无法更好地解释它。

–乔
17年9月1日在15:22