クエリの検索引数に CHECKSUM 列が明示的に含まれていない限り、SQL Server は自動的に CHECKSUM/ハッシュ インデックスを使用しないようです。これは問題です。なぜなら、私はテーブルをクエリするアプリケーションを制御しておらず、そのパフォーマンスを損なわない可能性があるからです。
クエリを変更して新しい CHECKSUM/ハッシュ カラムを含めずに、SQL Server に新しい CHECKSUM/ハッシュ インデックスを使用させる方法はありますか?
再現スクリプト
CREATE TABLE big_table
(
id BIGINT IDENTITY CONSTRAINT pk_big_table PRIMARY KEY,
wide_col VARCHAR(50),
wide_col_checksum AS CHECKSUM(wide_col),
other_col INT
)
CREATE INDEX ix_checksum ON big_table (wide_col_checksum)
いくつかのテスト データを挿入します。
SET NOCOUNT ON
DECLARE @count INT = 0
BEGIN TRANSACTION
WHILE @count < 10000
BEGIN
SET @count = @count + 1
INSERT INTO big_table (wide_col, other_col)
VALUES (SUBSTRING(master.dbo.fn_varbintohexstr(CRYPT_GEN_RANDOM(25)), 3, 50), @count)
IF @count % 1000 = 0
BEGIN
COMMIT TRANSACTION
BEGIN TRANSACTION
END
END
COMMIT TRANSACTION
INSERT INTO big_table (wide_col, other_col)
VALUES ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 9999999)
レガシー クエリ。Clustered Index Scan (BAD) の原因:
SELECT * FROM big_table
WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
クエリを更新しました。NonClustered Index Seek の原因 (良い):
SELECT * FROM big_table
WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
AND wide_col_checksum = CHECKSUM('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
バックグラウンド
私のテーブルは非常に大きく (数億行)、いくつかのインデックス (~ 20) があり、そのすべてが必要です。インデックス付きの列の一部は少し幅が広く (~ 50 バイト)、重複する値がほとんどありません。列は等しい場合にのみ検索されます。テーブルは常に挿入されます。
上記のサンプル テーブルの「通常の」インデックスと CHECKSUM/ハッシュ インデックスを比較したテーブルを次に示します。100 万行のテーブルで新しく再構築されたインデックスからのデータ:
ページ圧縮だけでは、サンプル データにはほとんど効果がありません (実際のデータはもう少し圧縮率が高くなるはずです)。ハッシュ インデックスは、4 分の 1 のインデックス サイズ削減を達成します。ハッシュ インデックスのページ圧縮により、インデックス サイズが 6 分の 1 に縮小されます。
ハッシュインデックスを使用する私の目的は次のとおりです。
- メモリ内のこれらのインデックスのサイズを縮小して、SQL Server が RAM 内により多くの部分をキャッシュできるようにし、物理的な読み取りを回避します。
- インデックスのストレージ サイズを減らします。
- INSERT 操作のインデックス I/O を減らします。