インデックスは,巨大なデータベースに対して空間データベースを利用できるようにするためのものです.インデックスが無い場合,図形についての全ての検索はデータベース中の全てのレコードの"sequential scan"が必要となるでしょう.インデックスは,特定のレコードを見つけるためにすばやく探索できる検索ツリーにデータを組織化することにより,検索をスピードアップします.PostgreSQLは既定でB-Tree,R-Tree,GiSTの3種類のインデックスをサポートします
B-Treeは,一つの軸にそって格納できるデーたに大して使われます;たとえば,数字,文字,日付けです.GISデータは一つの軸にそって合理的に格納することができません((0,0)と(0,1)と(1,0)のどれが大きいですか?).そのため,B-Treeインデックスはわれわれにとっては無用です.
R-Treeはデータを長方形に分割して,それをまたサブ長方形に分割し,それをまたサブサブ長方形に分割し,以下同様に続きます.R-TreeはGISデータのインデックスとしていくつかの空間データベースで塚輪低ます.しかし,PostgreSQLのR-Treeの実装はGiSTの実装ほど頑丈(robust)ではありません.
GiST (Generalized Search Trees)インデックスは, データを「一面のもの("things to one side")」,「重なるもの("things which overlap")」,「含まれるもの("things which are inside")」に分解し,GISデータを含む広範囲のデータタイプで使えるようにします.PostGISはGISデータのインデックシング,GiSTのトップでR-Treeインデックスの実装を使っています.
GiSTは"Generalized Search Tree"の略語で,インデックスの汎用形式です.GISのインデクシングに加えて,通常のB-Treeインデックスにあてはめられない(not amenable)全ての種類の不規則なデータ構造(整数配列,空間データ等)の検索をスピードアップするために使われます.
ひとたびGISデータテーブルが数千行を上回れば,データの空間的な検索のスピードアップの為にインデックスを作りたくなるでしょう(すべての検索が属性ベースで無い限り.この場合,属性フィールドに通常のインデックスを作りたくなるでしょう).
"geometory"カラムのGiSTインデックスを構築するための構文は以下のようになります:
CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] GIST_GEOMETRY_OPS ); |
空間インデックスの構築は計算的に激しい課題です:およそ100万行のテーブルを300MHzのSolarisマシンで,GiSTインデックスの構築に約1時間かかることが分かっています.インデックスを構築した後,PostgreSQLにクエリの計画を最適化するために使われるテーブルの統計値(statisticS)を集めさせることは重要です:
VACUUM ANALYZE; |
PostgreSQLにおいてGiSTインデックスはR-Treeインデックスより2つの利点があります.最初は,GiSTインデックスは"null safe"です.これは,null値を含むカラムのインデックスを作ることができることを意味します.2つ目は,GiSTインデックスはPostgreSQLの8Kのページサイズより大きなGISを扱うときに重要な"lossiness"の概念(concept)をサポートします.LossinessはPostgreSQLにオブジェクトの「重要な("important")部分だけをインデックスに格納することを許します--GISオブジェクトの場合,ちょうどbounding boxになります.8Kより大きなGISオブジェクトはR-Treeインデックスに構築プロセスでの失敗を引き起こすでしょう.
普通,インデックスは見えないところでデータアクセスをスピードアップする:一度インデックスが作られると,クエリプランナはユーザに意識させること無くクエリプランをスピードアップするためにインデックスの情報を使うタイミングを決定します.不幸にも,PostgreSQLのクエリプランナはGiSTインデックスの利用をあまり最適化していません.そのため時々,空間インデックスを使うべき検索が,既定のテーブル全体の逐次走査(sequence scan)となります.
もし,空間インデックスが(ついでに属性インデックスも含めて)使われていないことを発見したら,あなたが行える一組のことがあります:
最初に,問題があるテーブルで"VACUUM ANALYZE [テーブル名]"コマンドを実行したかを確認してください."VACUUM ANALYZE"はクエリプランナにインデックスの利用を決定するためのよりよい情報を提供するために,テーブル中の数字と値の配分(distributions of number)についての統計を集めます.とにかく定期的にデータベースにvacuumeを行うべきです--多くのPostgreSQLデータベース管理者はオフピークのcronジョブとして定期的に"VACUUM"を実行しています.
vacuumが上手くいかない場合,"SET=OFF"コマンドを使ってインデックス情報を使うことをプランナに強制することもできます.このコマンドは本当に慎重に,空間インデックスのクエリだけで使うべきです:一般的に,プランナは通常のB-Treeインデックスを使うタイミングについて,あなたより良く知っているといわれています.一度クエリを実行すると,他のクエリが通常どおりプランナを利用するために,"ENABLE_SEQSCAN"をセットしなおすことをと考えるべきです.
注:バージョン0.6では,"ENABLE_SEQSCAN"でインデックスの利用をプランナに強制することは,必要とすべきではありません(should not be necessary).