[InterDB] [著者HP] [PREVIOUS][UP][NEXT]

Copyright @ 2009, Suzuki Hironobu @ InterDB


■2-04■ プランナ


ここでは、プランナの処理を説明します。プランナの処理は、単一テーブルの問い合わせ(Simple Query)と、複数テーブルを結合する問い合わせ(Join Query)で異なります。

単一テーブルの問い合わせ(Simple Query)

問い合わせを行うテーブルについて、逐次スキャンを使った問い合わせ計画を作成します。
インデックスが定義されている場合は、そのインデックスを使った問い合わせ計画も作成します。

複数テーブルを結合する問い合わせ(Join Query)

問い合わせ文に複数テーブルの結合がある場合には、結合条件の処理順序を考慮しつつ、次に示すテーブル結合方式による実行可能な計画を列挙します。


    (1)入れ子反復結合(nested loop join)
    tb1 の行毎に、tb2が1回読み出されます。テーブルの読みだし回数はtb1とtb2のテーブル行数の積となるので、この結合は比較的小さなテーブル間でしか使われません。

    (2)マージソート結合(merge join)
    結合前に、それぞれのテーブルを結合属性でソートします。例えば次のSELECT文の場合、テーブル“tb1”について列“a”をキーとしてソートします。テーブル“tb2”についても同様です。

    SELECT tb1.a FROM tb1, tb2 WHERE tb1.a = tb2.a; 
    

    結合はソート済のテーブル間で行います。テーブルの読みだし回数は最悪でもtb1とtb2のテーブル行数の積、平均的にはどちらかのテーブル行数に比例した回数となるので、入れ子反復結合よりは少ないのですが、事前にソート処理が必要です。

    (3)ハッシュ結合(hash join)
    結合前に、結合属性をキーとして一方のテーブル(tb1)のハッシュテーブル(補足 1) を作ります。結合は、他方のテーブル(tb2)を逐次読みだし、ハッシュテーブルを使って先のテーブル(tb1)の値と結合します。テーブルの読みだし回数はマージソート結合と同程度、かつ事前のソート作業も不要ですが、大きなテーブルを処理する場合にハッシュテーブルがメモリに入りきらなくなると処理速度が低下します。


これら3つの結合方式の概念図を【図,2-4】に示します。

※この図は技術評論社刊「PostgreSQL完全攻略ガイド」(著:石井達夫)のP487〜488の図を参考にしました。

図.2-4 3つの結合方式


いつも3つの結合方式による問い合わせ計画が列挙されるのではなく、テーブルの大きさや結合条件などによって結合方式が複数選ばれ、それらを使った問い合わせ計画が列挙されます。

処理の実際

複数テーブルを結合する問い合わせ(Join Query)のプランナの処理について、実例を使って説明します。
gccのコンパイルオプションにマクロ"OPTIMIZER_DEBUG"を設定してPostgreSQLを再インストールすると、列挙された問い合わせ計画がすべて標準出力に出力されます(補足 2)。
この機能を使って、実際に次のSQL文の問い合わせ計画を表示してみましょう。

SELECT tb1.a, tb2.a FROM tb1, tb2 WHERE tb1.b = tb2.b; 

はじめに、プランナはテーブル毎の検索方式でコストを求めます。


    (1)テーブルtb2の問い合わせ計画

    RELOPTINFO (2): rows=9 width=82 
       joininfo (1): tb1.b = tb2.b 
       path list: 
       ???Path(2) rows=9 cost=0.00..1.08 
    

    (2)テーブルtb1の問い合わせ計画
    RELOPTINFO (1): rows=8 width=52 
       joininfo (2): tb1.b = tb2.b 
       path list: 
       ???Path(1) rows=8 cost=0.00..1.07 
    

    これらの結果を基に2つのテーブル結合方式(ここでは入れ子反復結合とハッシュ結合)による問い合わせ実行計画を列挙します。つまり、最終的に列挙される問い合わせ計画は入れ子反復結合とハッシュ結合の2つです。

    (3)上記SELECT文の実行計画

    RELOPTINFO (1 2): rows=9 width=134 
       path list: 
         HashJoin(1 2) rows=9 cost=1.09..2.37 
         clauses: tb1.b = tb2.b 
            ???Path(2) rows=9 cost=0.00..1.08 
            ???Path(1) rows=8 cost=0.00..1.07 
         Nestloop(1 2) rows=9 cost=0.00..10.61 
            clauses: tb1.b = tb2.b 
    	???Path(1) rows=8 cost=0.00..1.07 
    	???Path(2) rows=9 cost=0.00..1.08 
    


オプティマイザは列挙された2つの問い合わせ計画から、ハッシュ結合のコスト(2.37)と入れ子反復結合のコスト(10.61)を比較し、ハッシュ結合を選択します。

補足


(1)
ハッシュテーブルはハッシュ法で利用されるテーブル(正確にはリストを要素とする配列)です。ハッシュ法はデータを高速にみつけ出す手法の一つで、データに直接できるように予めハッシュテーブルにデータを並べかえて保存します。
詳細は「はじめてのアルゴリズム入門」河西朝雄(技術評論社)などを参照してください。

(2)
これは開発者むけのデバッグオプションです。コンパイルの手順は次のとおりです。


postgres> make clean 
postgres> CFLAGS=-DOPTIMIZER_DEBUG ./configure 
postgres> make; make install 



[PREVIOUS][UP][NEXT]