パフォーマンスに問題がある古いアプリケーションがあります。私はそれを、システム内の確実に注意が必要ないくつかのスポットに絞り込みます。
このアプリで参照されている1つのテーブルが見つかり、1,332,730,786レコードが含まれています。
Table IDSelection
IDType varchar(20) NOT NULL,
SelectID int NOT NULL,
UnID int NOT NULL,
Batch int NULL
テーブルには次のインデックスがあります
IX_IDSelection_UnID nonclustered located on PRIMARY UnID
PK_UIDSelection clustered, unique, primary key located on PRIMARY SelectID, IDType, UnID
私の懸念は1です。このテーブルには、空の文字列(ただしNULLではない)であるIDTypeのいくつかのエントリを持つ複合主キーがあります。 2.このテーブルに対して以下のような単純なSELECTクエリを実行すると、かなり時間がかかります。
select * from IDSelection where IDType <> '' and Batch is not NULL ORDER by Batch desc -- cluster index scan
select * from IDSelection where Batch = 9977 -- 8 minutes run for 19 records
select * from IDSelection where IDType = 'ParentID' and Batch is not NULL -- 9 min 3614603 rows
以下のようにWHERE句でインデックス付きのUnIDを使用すると、パフォーマンスが向上します
SELECT * FROM IDSelection where UnID = 1093510
インデックスの断片化はここでは問題になりません。 IDの主キーを追加し、[非クラスター化一意インデックス]のヘルプとして現在の複合キーを作成するのに役立ちますか?他にどのようなオプションがありますか?
DBバージョンはMS SQL 2014 Enterpriseです
追加のインデックスを作成するのにどのくらい時間がかかると思いますか? DMLはどのくらいの頻度で実行されますか?このテーブルは頻繁に読み取られていますか?
この怪物には10億行以上あるので、列SelectID, IDType, UnID, Batch
そして適切なインデックスをそこに適用します。
これらには、Batch
で始まるインデックスが必要です。最初の場合は_ORDER BY
_、2番目の場合はWHERE
です。
_select * from IDSelection where IDType <> '' and Batch is not NULL ORDER by Batch desc -- cluster index scan
select * from IDSelection where Batch = 9977 -- 8 minutes run for 19 records
_
これにはINDEX(ParentID, Batch)
がこの順序で必要です:
_select * from IDSelection where IDType = 'ParentID' and Batch is not NULL -- 9 min 3614603 rows
_
あなたはすでにUnID
にインデックスを持っています(または少なくともそれから始まっています)、したがってこれは高速です:
_SELECT * FROM IDSelection where UnID = 1093510
_
すべての列が本当に必要な場合を除き、_*
_を使用しないでください。列の小さなセットのみを選択する必要がある場合は、それらをインデックスの最後に追加して、「カバー」することができます。