SQL-Server多租户数据分区建议

cyr*_*sly 5 database-design sql-server partitioning azure-sql-database multi-tenant

我很感激有关分区(或不分区)多租户业务应用程序的设计注意事项的意见。所有数据表都使用一个复合键,类似于:

CREATE TABLE SomeTable(
  TenantId SMALLINT NOT NULL,
  ID INT NOT NULL,
  SomeData ...,
  CONSTRAINT [PK_SomeTable] PRIMARY KEY CLUSTERED (TenantID, ID)
)
Run Code Online (Sandbox Code Playgroud)

几乎所有读取都以特定的租户 ID 为键。写入由租户 ID 随机输入,但 3-5 天内的任何数据在此之后往往永远不会改变。

问题

  1. 如果我不分区,是 (tenantID, id) 或 (id,tenantid) 更好的选择。假设读取都是由租户 ID 进行的,写入是由租户 ID 随机写入的,并且每晚有足够的停机时间来运行维护计划。
  2. 为每个租户 ID 创建单独的分区有什么优点和缺点?
  3. 如果tenantID 是第一个键,分区会减少页面碎片吗?
  4. 如果分区在主文件中,是否会改变参数?
  5. 如果有 10 或 1000 个分区,它会改变参数吗?
  6. 答案是否取决于我使用的是 SQL 2016 还是 SQL Azure?

Dav*_*oft 8

如果我不分区,是 (tenantID, id) 或 (id,tenantid) 更好的选择。假设读取都是由租户 ID 进行的,写入是由租户 ID 随机写入的,并且每晚有足够的停机时间来运行维护计划。

(tenantID,id) 是更好的排序,因为它为每个租户的数据创建位置。

为每个租户 ID 创建单独的分区有什么优点和缺点?

优点:分区操作可用于对单个租户进行操作。例如切换、截断、重建。

缺点:维护,以及可能的分区拆分以添加新租户的成本。

但请看:

如果tenantID 是第一个键,分区会减少页面碎片吗?

否。每个租户的行在索引中在逻辑上和物理上大部分是连续的。每个租户基本上都会有一个或几个片段。所以虽然分区会减少碎片,但没有分区应该不是问题。

如果分区在主文件中,是否会改变参数?

不,那是分开的。所有分区都应该放在一个文件组中,除非有充分的理由将它们分开。您可能会为某些特殊租户创建一个单独的文件组,但我不建议这样做。

如果有 10 或 1000 个分区,它会改变参数吗?

不,除了它加剧了分区的维护问题。

答案是否取决于我使用的是 SQL 2016 还是 SQL Azure?

不。

但是退一步说,您应该计划拥有多个联合数据库来保存您的租户数据。您仍然可以采用多租户数据库设计,但在最终状态下,您将混合使用多租户和单租户数据库。在数据库中隔离租户有许多重要的优势。

  1. 租户数据是隔离的。这对于向您的客户进行销售非常重要,并且可以轻松确保租户永远不会看到彼此的数据。
  2. 您可以单独升级和修补租户。
  3. 您可以一次免费移动、备份、恢复和导出租户。至关重要的是,这为您提供了单个租户的时间点恢复。
  4. 数据库是一个真正的安全边界,您可以让用户只能看到单个租户的数据。
  5. 您不必编写租户导出和租户导入过程来将租户从一个数据库移动到另一个数据库,否则您将不得不编写。
  6. 您可以单独扩展租户,为大型或高级租户提供对服务器资源的差异化访问,甚至为他们提供自己的专用资源。这使您的解决方案更易于管理、降低风险并为您创造定价机会。
  7. 每个租户都有自己的查询计划缓存,因此您没有针对用于查询大租户数据的小租户优化的查询计划,反之亦然。您可以查看每个租户的性能指标。