データベース用ストレージを効率的に管理するには,どのオブジェクトがディスク容量を消費するのかということと,そのオブジェクトはSQL Serverによってどのように格納されるのかということを理解する必要がある。

 例えば,SQL Server 2000では,スペース使用状況を管理するために単純なシステム・テーブルを一つだけ使っている。ディスク・スペースを消費するのは二つのオブジェクトだけであり,ユーザー・データを格納するためのページは3種類しか存在しない。この構造は,管理するのは比較的簡単だが,いくつかの制限もある。特に,SQL Serverがラージ・オブジェクト(LOB)データを格納および取得する方法が影響を受ける。

 SQL Server 2005の拡張ストレージ・モデルでは,ディスク・スペースを消費するオブジェクトの数と種類が増え,可変長のLOBデータの格納に関してこれまで以上に多様な選択肢が提供されている。さらに,パーティション分割されたデータを異なる複数の場所に格納する機能が追加されている。

 ここではまず,SQL Server 2000の基本ストレージ・モデルを確認して,その後でSQL Server 2005がどのようにデータ用ディスク・スペースを管理するのか調べてみよう。

SQL Server 2000のストレージ・スペース

 SQL Server 2005より古いSQL Serverのリリースでは,データベースの中で実際にストレージ・スペースを使うのはテーブルとインデックスの二つだけである。それ以外の方法で情報をテーブルやインデックスに格納することはほとんどない。

 SQL Server 2000には,アプリケーション情報を格納するページとして3種類が存在する。インデックス・ページ,データ・ページ,そしてLOBデータを格納するためのページである。LOBデータとは,text,ntext,またはimageのいずれかのデータ型として定義されるデータだ。

 このような比較的単純なストレージ・モデルでは,SQL Serverでディスク・スペースを消費するオブジェクトをすべて,システム・テーブル(sysindexes)だけで管理できる。sysindexesには,テーブル一つにつき1行と,テーブルに定義されるインデックス一つにつき1行が存在する。さらに,テーブルにLOBデータが含まれる場合は,それを管理するための行がテーブル一つにつき1行存在する。sysindexesのすべての行には,テーブル,インデックス,またはLOBデータが消費するディスク・スペース容量に関する情報と,それらの構造を保持しているページがどこにあるかを示す情報が含まれている。

 テーブルにクラスタ化インデックスが定義されている場合は,テーブルのデータもインデックスの一部とみなされる。したがって,sysindexesのデータ行は実際にはインデックス行である。sysindexesには,クラスタ化インデックスが定義されているテーブル一つに対してインデックスID (indid)の値が1であるような行が一つ存在する。

 クラスタ化インデックスが定義されていない場合は,テーブルデータは組織化されない。そのようなテーブルはヒープと呼ばれる。sysindexes内のヒープのindid値は0である。インデックスを追加すると,indid値が2から250の範囲の値であるような行が,sysindexesに1行追加される。

 sysindexesのindid値が含まれる列のデータタイプはtinyintである。これは,最大255までの値を格納できることを意味する。インデックスのindid値は251から254までが予約され,さらにSQL Server 2000がLOBデータを保持しているデータの管理用に255を使っているので,最大値は250になる。SQL Serverは,テーブルやインデックスのスペース管理用に使っているsysindexesの列を,そのテーブルの任意の行または列に格納されているすべてのLOBデータが消費する総容量の管理にも使っている。

 sysindexesテーブルの単純さはその強みの一つでもある。しかし,SQL Server 2005では,sysindexesテーブルの構造に関する様々な問題が解決されている。

 例えば,sysindexesテーブルには,インデックス付けされていない,列の統計情報を格納するための行が存在する。このことはそのような統計情報に一意なindid値を割り当てる必要があることを意味する。したがってテーブルに大量の統計情報が存在する場合は,テーブルに必要なインデックスをすべて作成する前に使用できるindid値が枯渇する可能性がある。

 また,sysindexesではタイプの異なるページを使用したり,ページ間の関係が変わるような設計変更を行うことはできない。最後に,SQL Server 2000では,LOBデータをテーブルに関連付けられた特殊データとみなしているので,インデックスにはLOBデータを含めることはできない。しかし,SQL Server 2000およびそれ以前のリリースでは,text型,image型,またはntext型の列にインデックスを作成することはできないので,sysindexesの構造をそのまま使うことができた。しかし,SQL Server 2005では事情が変わった。

データの新しい格納方法

 SQL Server 2005でも,データやインデックスの通常の行を格納する必要があるという点は変わっていない。しかし,新しく導入されたvarchar(max)データ型を使うと,通常の行データとLOBデータの両方を保持するための列を定義することができる。さらに,varchar(max)型の列を含むインデックスを定義することができる。このことは,インデックスにLOBデータが含まれる可能性があることを意味している。

 また,サイズの大きなvarcharフィールドを複数定義することができるが,最大長としてMAXではなく,SQL Server 2000の最大長である8000までの整数を指定することができる。このテクニックを使うと,複数のサイズの大きいvarchar列に連続してデータを格納することによって,SQL Serverで1ページ内に格納可能な最大長を超える長さの行を設定できる。SQL Serverでは,行に収まらないvarcharフィールドは,単純にROW_OVERFLOWページと呼ばれる特殊ページに格納される。ROW_OVERFLOWページには,インデックス行も格納可能である。

 SQL Server 2005では,テーブルやインデックスをパーティション分割して,その行を異なる複数の場所に格納することができる。しかし,sysindexesでは,単一構造を複数のストレージ領域に分散配置することを表現できない。

 そこで,SQL Server 2005では,インデックスをテーブルに従属するストレージ構造とみなすのではなく,インデックスとテーブルが対等な立場にあると考える必要がある。テーブルとインデックスはどちらも通常の行,LOBデータ,およびROW_OVERFLOWデータを格納する必要がある。また,両者はどちらもパーティション分割可能である。