在SQL Server上的多租户环境中定义PK

时间:2015-11-13 14:57:26

标签: sql sql-server

我看到在多租户环境中选择PK的不同意见。让我们说一个有员工表。我创建了这样的Employee表:

EmployeeId INT IDENTITY PRIMARY KEY,
TenantId INT,
FirstName NVARCHAR(100),
LastName NVARCHAR(100)

我知道我需要在所有查询中使用TenantId,所以我在TenantId上创建了一个非集群索引,所以我可以写一些像这样的查询:

如果我需要一个特定租户的所有员工:

Select EmployeeId, FirstName, LastName
where TenantId = 1

如果我需要一名雇员为一个特定租户:

Select EmployeeId, FirstName, LastName
where EmployeeId = 1 and TenantId = 1 

现在在Employee表上测试大约100000条记录和一个单一租户我在第一个查询上得到完全扫描(我想这是正常的,即使我在TenantId上定义了非集群索引,因为我的表中有一个租户所以它需要扫描所有表格)和第二个索引搜索。

这是一个好方法,我是否也需要在群集索引中添加TenantId?

2 个答案:

答案 0 :(得分:2)

您的问题没有简单的答案。您似乎有一个低基数列,并希望查询该列。因此,您将返回许多行。您已经在一个值的情况下观察到了这一点 - >获取所有行。

如果您有10个随机分布在100,000行中的租户,那么SQL Server可能仍会进行全表扫描,因为它希望所有页面至少有一个您要查找的记录。这就是非聚集索引在具有高基数的列上最有效的原因(这意味着很少行具有任何给定值)。

使用tenant上的聚簇索引,您将在1/5的页面中找到所有行。查询应该更快。但是,查询仍然返回大量数据,因此更快的表扫描是否具有整体优势是一个悬而未决的问题。

而且,这需要付出代价。表{1}}不再出现在表的末尾,因此页面拆分变得更加常见。 INSERT租户需要删除并重新插入数据,而不是修改记录(并且其他工作可能会产生锁定影响)。这些可能是重要的考虑因素。

聚合索引在低基数列上有用的常见情况是最近的数据"问题。如果你有一个表,只有1%是最新数据(或有效或其他),那么该列上的聚集索引可能是一个巨大的胜利。

最后,如果UPDATE确实基数较低,您可以考虑按此列对表进行分区。这可能会给你两全其美,至少对于你建议的两个查询。

答案 1 :(得分:0)

PRIMARY KEY只是一个标签,表示这是桌子上的主要查找!真正的问题是你使用CLUSTERED索引的哪个键?个人来自你发布的内容,我过去看过的内容以及了解引擎 - 我在TentantId上集群,EmployeeId还在EmployeeId上添加了一个非聚集的唯一键,这是你的代理键。因为你聚集在TentantId和B + Trees的性质上,那么你的租户将会在一起(按顺序)。此外,有助于稍后进行分区......