IDENTITY
列( )を持つ非常に大きなテーブルがありbigint
、このテーブルが削除される可能性がある場合、アドレス空間(使用可能なID)の断片化により速度が低下しますSELECTS
か?
明確化:
アドレス空間の断片化とは、テーブルから行を削除するときに発生するディスク上の断片化ではなく、ID列の値に残っているギャップを意味します。
IDENTITY
列( )を持つ非常に大きなテーブルがありbigint
、このテーブルが削除される可能性がある場合、アドレス空間(使用可能なID)の断片化により速度が低下しますSELECTS
か?
明確化:
アドレス空間の断片化とは、テーブルから行を削除するときに発生するディスク上の断片化ではなく、ID列の値に残っているギャップを意味します。
明らかに、これはテストを実行しなければ確実に知ることはできません。ただし、連続または断片化されている場合、実行が速くなったり遅くなったりすることはないと推測します。
列にインデックスが作成されていると仮定すると、SQL Server はインデックスを B ツリーに格納します。このツリーのノードは、システムのページング システムに最適なサイズになるように設計されています。ノード内の検索は、インデックスの断片化に関係なく、正しい子ノード ページを識別します。ページの読み込みにかかる時間は、ノード内での検索にかかる時間を圧倒するので、断片化がルックアップ時間に影響を与えるとは思いません。
一方、列にインデックスが付けられていない場合、SQL Server はいずれにせよ完全なテーブル スキャンを実行する必要があるため、値の分布は時間にまったく影響しません。
影響を与える可能性のある場所の 1 つは、クエリ プランの最適化です。SQL Server は、適切なパフォーマンスを提供するクエリ プランを選択できるように、列の内容のヒストグラムを格納します。断片化により、考えられた別の計画ほど良くない計画を選択する可能性があるように思えます。これは、列の統計が最新でない場合に当てはまります。統計が最新であれば、断片化が検出され、オプティマイザはその情報を考慮に入れることができます。
テーブルのインデックス方法によって異なります。列にクラスター化インデックスも配置すると仮定すると、その列を使用するすべての選択ステートメントは非常に高速になります。極端な場合、範囲スキャンを実行している場合、追加のページをメモリに取り込む必要があるかもしれませんが、ID ではそのようなことを行うことはほとんどありません。通常、シークによってこれらの行を取得しています。
特に大量の削除を行っている場合は、断片化を解消するメンテナンス プランを用意する必要があります。ただし、これは私の得意分野ではないことを認めなければならないので、SQL 2008 やストレージ メディアによってこれが不要になるかどうかはわかりません。
いいえ。
インデックス列でない場合は、エンジンがテーブル スキャンを実行するため、断片化は問題になりません。(実際のクエリ/結合によっては、エンジンは必ずしもテーブル スキャンを行っているとは限りませんが、列自体の観点からは、エンジンはテーブル スキャン以外に何もする必要はありません)
インデックス付きの列の場合、データの挿入または削除中に展開または縮小されるツリー構造にインデックスが格納されます。このツリー構造について知っておく必要があることの 1 つは、データを順番に挿入しても「断片化」されているということです。ここでの断片化は、ディスク割り当て単位の意味ではありませんが、ツリー内の各ノードは、対象となるデータ範囲に対して完全には使用されていません。断片化の目的は、ツリーの再構築が頻繁に行われるのを避けることです。エンジンは、インデックス ツリーを再構築するときに占有率を使用します (インデックスの作成時に指定できます)。そのため、ID が連続しているかどうかに関係なく、いくつかの「ギャップ」を含むより大きなストレージ スペースに格納されます。列を削除しても、パフォーマンスに顕著な違いが生じることはありません。
ただし、データベースもページごとにストレージ領域を割り当てます。つまり、断片化と関連するパフォーマンスの問題が発生します。しかし、あなたの質問には、これは id 列の削除とは何の関係もありません。