メモリ最適化されたハッシュ インデックスのパフォーマンスに関する一般的な問題のトラブルシューティング
このトピックはハッシュ インデックスの一般的な問題のトラブルシューティングと回避方法に焦点を当てて説明します。
検索を使用するにはハッシュ インデックス キー列のサブセットが必要になる
問題: ハッシュ インデックスでは、ハッシュ値を計算し、ハッシュ テーブル内の対応する行を見つけるために、すべてのインデックス キー列の値が必要です。 したがって、クエリに 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) に等値述語がありますが、テーブルには 2 列 (o_id、od_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」を参照してください。