PostgreSQLのマルチカラムbtreeインデックスを利用して、2つのテーブル間で厄介な結合を実行しようとしています。PostgreSQLマルチカラムインデックスの比較( "<" and ">")演算子
Table "revision_main"
Column | Type | Modifiers
----------------+------------------------+-----------
revision_id | integer |
page_id | integer |
Indexes:
"revision_main_pkey" UNIQUE, btree (revision_id)
"revision_main_cluster_idx" btree (page_id, "timestamp") CLUSTER
この表には、wikiの改訂版(〜3億行)が含まれています。私のテーブルにはもっと多くの列がありますが、私はこの例のためにそれらを破棄しました。なぜなら、それらは重要ではないからです。
Table "revert"
Column | Type | Modifiers
--------------------+---------+-----------
page_id | integer |
revision_id | integer |
reverted_to | integer |
Indexes:
"revert_page_between_idx" btree (page_id, reverted_to, revision_id) CLUSTER
この表には、復帰改訂版(約2200万行)が含まれています。リビジョンが元に戻った場合、revision_idはrevision_mainテーブルに行を持ち、revision_idとrevision_idの間にrevision_idがあり、同じpage_idを共有します。 (興味があればhttp://en.wikipedia.org/wiki/Wikipedia:Revertを参照してください)
復帰したリビジョンを取得するためにこれらの2つのテーブルを結合するのは簡単です。ここで私が作ってみたものです:元に戻すにクラスタ化インデックスが(したがって、「<」のような比較演算子をサポートし、「>」)Bツリーインデックスであるべきにもかかわらず
explain SELECT
r.revision_id,
rvt.revision_id
FROM revision_main r
INNER JOIN revert rvt
ON r.page_id = rvt.page_id
AND r.revision_id > rvt.reverted_to
AND r.revision_id < rvt.revision_id;
QUERY PLAN
----------------------------------------------------------------------------------------------------
Merge Join (cost=4202878.87..15927491478.57 rows=88418194298 width=8)
Merge Cond: (r.page_id = rvt.page_id)
Join Filter: ((r.revision_id > rvt.reverted_to) AND (r.revision_id < rvt.revision_id))
-> Index Scan using revision_main_page_id_idx on revision_main r (cost=0.00..9740790.61 rows=223163392 width=8)
-> Materialize (cost=4201592.06..4536465.21 rows=26789852 width=12)
-> Sort (cost=4201592.06..4268566.69 rows=26789852 width=12)
Sort Key: rvt.page_id
-> Seq Scan on revert rvt (cost=0.00..438534.52 rows=26789852 width=12)
、クエリオプティマイザはしていません参加のために索引を使用し、「説明する」は、総費用が150億を超えると予測します(来年に行われる可能性があります)。
複数の列(btree)インデックスで比較演算子を使用することはできませんか?私は間違っているだけですか?
を私の経験では、コスト見積もりは実行時間を一貫して反映する傾向があります。その一方で、数字が何を意味するかはわからないので、私はあなたの理解には容認します。クエリを実行して番号を無視することをお勧めしますか? – halfak
@halfak:もっと詳しく見てみましょう。データベースは小さなテーブルとの結合を開始するのが好きです。 revision_mainに(page_id、revision_id)のインデックスを追加すると、より効率的なクエリが得られる可能性があります。それはまた悪化するかもしれません。しかし、それが失敗した場合、それをより効率的にする唯一の方法は、より少ないデータを求める方法を見つけることです。 – btilly