我正在从事一个新项目,并且正在设计系统背后的 Microsoft SQL Server 数据库。
该系统将包含无限数量的客户,每个客户都有多个用户。每个客户都将拥有自己的数据子集,而且数据量将会非常庞大。最坏的情况是每个客户每月跨多个表大约 5+ 百万行。
为了优化每个客户的性能,我正在考虑一个包含一个系统数据库和多个客户数据库的系统。我的想法主要是我看不出一个客户为什么要查询其他客户的数据。我看到的问题是这个解决方案会导致客户数据库和系统数据库之间的关系(跨数据库关系)。
我是否过度考虑了性能问题?
假设您还没有开始编写应用程序或数据库,但确实了解数据的范围(即使随着时间的推移会有所改变):不,您没有想太多。我不会花几个月的时间思考系统设计的这一方面,但完全不考虑它有点愚蠢,因为重构应用程序代码比重构数据库要容易得多(因为数据库包括“状态”)。
我对多租户系统的偏好,尤其是在处理大量数据和/或客户端之间数据大小差异很大的情况下,是走数据库每个客户的路线。任何方法显然都有优点和缺点,但这是我经历过几次并尝试两种方法后看到的:
优点
CustomerID
表中都有一个字段(查找表除外)。这使索引编制和性能调整变得复杂。缺点
关于拥有单个 SystemData 数据库的想法以及无法跨数据库 FK 的相关问题:您希望有多少系统查找数据?假设它不是 1 GB 的数据,您可以在每个名为“系统”或“通用”或“查找”或其他名称的客户数据库中创建一个架构,并将数据加载到该架构中的所有客户数据库中。然后你可以 FK 到那些表。通过为每个客户拥有一个数据库,您将已经需要一个发布过程,以完全相同的方式更新每个客户数据库的代码和模式(这样它们始终与通用结构同步),因此更新查找表是正确的进入那个过程。这里的主要缺点是您要为每个客户数据库复制此数据,大概 200 次?但那是多年来的过程。你不是
另外,请记住,表分区不是“分片”(就像您可能会想到的 MongoDB 或 PostgreSQL/GreenPlum 等)。它并不是要神奇地解决多租户或分布式数据的问题。它旨在处理快速有效地处理批量数据加载和卸载的问题。它在预期目的方面做得很好。有时它甚至可以帮助查询非常大的表(10 亿行或更多)。但是索引和统计信息仍然是针对每个表的,而不是针对每个分区的(尽管您可以为每个分区键创建过滤索引/统计信息以帮助弥补这一点)。虽然您可以(在较新的版本中)为每个分区重建索引,但从 SQL Server 2012 开始,索引不再“免费”
UPDATE STATISTICS WITH FULL SCAN
在进行 REBUILD 时,如果它们已分区!非分区索引仍然可以:-)。对于它的价值,我在一个多租户系统上工作,该系统确实尝试以这种方式使用表分区(这不是我的主意)。它引起了很多头痛、沮丧、额外的工作来试图修复奇怪的执行计划,并且在几年之后,大多数人一致认为它可能不应该被完成。