疑難排解記憶體最佳化雜湊索引的常見效能問題
本主題將焦點放在疑難排解以及解決與雜湊索引相關的常見問題。
搜尋需要雜湊索引鍵資料行的子集
問題: 雜湊索引需要所有索引鍵資料行的值,才能計算雜湊值,並在雜湊表中找出對應的資料列。 因此,如果查詢只包含 WHERE 子句中索引鍵子集的相等述詞,SQL Server無法使用索引搜尋來尋找與 WHERE 子句中述詞對應的資料列。
相反地,只要索引鍵資料行是索引中的前置資料行,像是磁碟非叢集索引和記憶體最佳化非叢集索引這類已排序索引就可支援在這些資料行的子集上進行索引搜尋。
症狀:這會導致效能降低,因為SQL Server需要執行完整資料表掃描,而不是索引搜尋,這通常是較快速的作業。
如何進行疑難排解: 除了效能降低之外,查詢計劃的檢查也會顯示掃描,而不是索引搜尋。 如果查詢相當簡單,則查詢文字和索引定義的檢查也會指出搜尋需要索引鍵資料行的子集。
請考慮下列資料表和查詢:
CREATE TABLE [dbo].[od]
(
o_id INT NOT NULL,
od_id INT NOT NULL,
p_id INT NOT NULL,
CONSTRAINT PK_od PRIMARY KEY NONCLUSTERED HASH (o_id, od_id) WITH (BUCKET_COUNT = 10000)
)
WITH (MEMORY_OPTIMIZED = ON)
SELECT p_id
FROM dbo.od
WHERE o_id=1
資料表的兩個資料行 (o_id、od_id) 上有雜湊索引,而查詢在 (o_id) 上有等號比較述詞。 因為查詢只有索引鍵資料行子集的相等述詞,所以SQL Server無法使用 PK_od 來執行索引搜尋作業;相反地,SQL Server必須還原為完整索引掃描。
因應措施: 有一些可能的因應措施。 例如:
重建索引做為非叢集類型,而不是非叢集雜湊。 記憶體優化的非叢集索引已排序,因此SQL Server可以在前置索引鍵資料行上執行索引搜尋。 範例產生的主索引鍵定義會是
constraint PK_od primary key nonclustered
。變更目前的索引鍵以符合 WHERE 子句中的資料行。
加入與查詢的 WHERE 子句中資料行相符的新雜湊索引。 在此範例中,產生的資料表定義如下:
CREATE TABLE dbo.od ( o_id INT NOT NULL, od_id INT NOT NULL, p_id INT NOT NULL, CONSTRAINT PK_od PRIMARY KEY NONCLUSTERED HASH (o_id,od_id) WITH (BUCKET_COUNT=10000), INDEX ix_o_id NONCLUSTERED HASH (o_id) WITH (BUCKET_COUNT=10000) ) WITH (MEMORY_OPTIMIZED=ON)
請注意,如果某個索引鍵值具有大量重複的資料列,則記憶體最佳化雜湊索引不會以最佳方式執行:在範例中,如果資料行 o_id 的唯一值數目比資料表中資料列的數目少許多,則在 (o_id) 上加入索引並不是最好的方式,較佳的解決方法是將索引 PK_od 的類型從雜湊變更為非叢集。 如需詳細資訊,請參閱< Determining the Correct Bucket Count for Hash Indexes>。