SQL Serverのインデックスは、クラスタ化インデックス、非クラスタ化インデックスともにBツリー方式の構造をとっています。Oracle
Serverの「ビットマップインデックス」に相当するものはありません。SQL Serverでは、Bツリーのルートからツリーをたどって目的のデータを探し出すことを「インデックスシーク」といいます。また、クラスタ化インデックスを作成したテーブルを全件検索するときなど、インデックスのリーフレベルのページチェーンをたどることを「インデックススキャン」といいます。パフォーマンスチューニングなどで「実行プラン」(Oracleの「実行計画」)を確認する場合に、結果に「インデックス」とあったとしても「スキャン」であれば全件検索している可能性もあるので、「スキャン」と「シーク」の違いは覚えておくべきでしょう。ちなみにSQL
Serverでは「クエリオプティマイザ」という機能が、もっとも効率的な実行プランをコストベースで決定します。
さて、すでに説明した通り、SQL Serverでは通常クラスタ化インデックスを作成しますので、よくあるテーブルの構成としてはクラスタ化インデックスを作成したテーブルに、さらに非クラスタ化インデックスが複数作られます。このとき、非クラスタ化インデックスのリーフレベルには非クラスタ化インデックスのキー値と、さらに実データであるクラスタ化インデックスのキー値を持ちます。非クラスタ化インデックスを使用して実データを参照するような処理がおこなわれるときは、図のように非クラスタ化インデックスシークをした後に、クラスタ化インデックスのキー値をもとにクラスタ化インデックスをルートからたどって、実際のデータ(クラスタ化インデックスのリーフページ)にたどり着くのです。
| ■ クラスタ化インデックスを使用して実データを参照 |
 |
 |
 |
インデックスは、値がある列の順番に並んでいるからこそ、新たにデータを挿入しようとしたときにページ分割が起こる可能性があります。たとえば社員番号がクラスタ化インデックスとして設定されているテーブルがあり、社員番号「100」「102」「103」の3レコードで「ページ」(Oracleのブロック)が一杯になっているとします。ここに新たに「101」を挿入すると、「100」「101」のページと「102」「103」のページに分割します。これに関しては、Oracle
ServerもSQL Serverも同じ動きをします。ページ分割自体、システムのオーバーヘッドですので、Oracle Server、SQL
Serverともにページ分割が起こらないようにインデックス作成時にある程度の空き領域を作っておきます。
Oracle Serverでは「PCTFREEパラメータ」でブロックの空き領域のパーセンテージを指定し、SQL Serverでは「CREATE INDEXステートメント」の「FILLFACTORオプション」で「何パーセント使用するか」を設定します。なお、FILLFACTOR値のデフォルトは0(100%使用)です。読取中心のOLAPのシステムではFILLFACTOR値は100%のままでも良いでしょう。FILLFACTORはクラスタ化インデックス、非クラスタ化インデックスともに、リーフレベルページの使用率として設定できます。
Oracle Serverでは「表」に対してもUPDATEの空き領域としてPCTFREE設定できますが、SQL Serverはクラスタ化インデックスを作成していないテーブルのページに対して、使用率は指定できません。FILLFACTOR値はあくまでインデックスのリーフレベルページに適用するものです。しかし通常はテーブルにクラスタ化インデックスを作成しますので、インデックスに対するFILLFACTORの設定ができれば問題ないわけです。
ページ分割による断片化の解消方法など、インデックスの保守の詳細はマイクロソフト認定トレーニングコース「#2073
Microsoft SQL Server 2000 データベースプログラミング」で扱っています。
|