2015-11-13 30 views
1

我在多租戶環境中看到關於選擇PK的不同觀點。假設有一張表Employees。我創建了我的僱員表是這樣的:在SQL Server上的多租戶環境中定義PK

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上定義了非集羣索引,我猜這是正常的,因爲我的表中有一個Tenant它需要掃描所有的表)和索引查找第二個。

這是一個好方法,我是否需要在集羣索引中添加TenantId?

+0

如果在TenantId –

+0

@stevenackley上有非聚集索引,則不應該進行掃描。 。 。不對。 SQL Server足夠聰明,在任何情況下都不會使用這樣一個簡單的規則。 (我相信你所說的在一些數據庫如MySQL和Postgres中是真的) –

回答

2

有沒有簡單的答案你的問題。您似乎有一個低基數列,並希望查詢該列。因此,您將返回多行。您已經在一個值的情況下觀察到了這一點 - >獲取所有行。

如果您有5個租戶隨機分佈在100,000行中,那麼SQL Server可能仍會執行全表掃描,因爲它期望所有頁面至少有一個您正在查找的記錄。這就是爲什麼非聚集索引在基數高的列上工作得最好(這意味着少數行有任何給定的值)。

使用tenant上的聚簇索引,則可以在頁面的1/5中找到所有行。查詢應該更快。但是,查詢仍然返回大量數據,所以這是一個懸而未決的問題,更快的表掃描是否有很大的總體收益。

而且,這是有代價的。 INSERT s不再發生在表的末尾,因此頁面拆分變得更加普遍。 UPDATE需要刪除並重新插入數據,而不是修改記錄(並且額外的工作可能會產生鎖定影響)。這些可能是重要的考慮。

聚類索引在低基數列上很有用的常見情況是「最新數據」問題。如果你有一個表,只有1%是最近的數據(或有效的或其他),那麼該列上的聚集索引可能是一個重大勝利。

最後,如果tenantid確實是低基數,則可以考慮按此列對錶進行分區。這可能會給你兩全其美,至少對於你提出的兩個問題。

+0

謝謝大家的回答 – cmonti

0

PRIMARY KEY是一個簡單的標籤,表明這是主表查詢!真正的問題是你使用CLUSTERED索引的哪個鍵?我個人從你發佈的內容,過去見過的內容以及引擎知道 - 我會在TentantId,EmployeeId上集羣,但還會在EmployeeId上添加一個非集羣唯一鍵,這是您的代理鍵。因爲你聚集在TentantId和B +樹的性質,那麼你的租客將會在一起(按順序)。此外,它適用於以後分區....

+0

這真的很混亂:(因爲我讀過,如果我們使用兩個列作爲PK,EmployeeId應該是第一個,然後是TenantId,因爲Employee是最具選擇性的列 – cmonti

+0

這對於撤消單行很好,但是,您是否有任何查詢可以撤回幾百/千行 - 如果您在代理鍵EmployeeId上進行集羣並且您指定了TenantId = 4,那麼該數據不是' t分組在一起 - 它分散在表中的所有範圍內,因此性能不會很好 - 基本上這就是爲什麼要爲它們編制索引的原因。集羣密鑰具有非集羣密鑰的副本,因此需要記住。你在做什麼。 –

相關問題