配列型インデックス
co-sakaです。こんにちは。
複数列インデックス - Ludia開発日記(昔の日記)の続きです。
マルチカラムインデックスはOR検索があまり高速でない。
他に方法がないのか?
これに対する解決方法を紹介します。
以下のテーブルで説明します。
=# CREATE TABLE book (title TEXT, header TEXT, body TEXT, author TEXT); =# INSERT INTO book VALUES('我輩は猫である', '日本', '我輩は猫である。名前はまだない。', '夏目漱石'); =# INSERT INTO book VALUES('日本国憲法', '日本', '日本国民は、正当に選挙された国会における代表者を通じて行動し', '伊藤博文'); =# INSERT INTO book VALUES('学問のすすめ', 'Japan', '天は人の上に人を造らず。人の下に人を造らずと云えり。', '福沢諭吉'); =# INSERT INTO book VALUES('Ludiaのすすめ', 'Japan', '日本語の全文検索が可能', 'co-saka');
マルチカラムインデックスを用いると、以下のようになります。
=# CREATE INDEX idx1 ON book USING fulltextb(title, header, body, author); =# SELECT title FROM book WHERE title @@ '日本' OR header @@ '日本' or body @@ '日本' OR author @@ '日本'; -- クエリ1 title ---------------- 我輩は猫である 日本国憲法 Ludiaのすすめ (3 rows) =# SELECT title FROM book WHERE title @@ '日本'; -- クエリ2 title ------------ 日本国憲法 (1 row)
クエリ1の場合、マルチカラムインデックスに対して、
@@の数だけ検索が実行されます。
(そして4つの検索結果が結合されます。)
これはあまり好ましくありません。
そこで、以下のように配列型インデックスを作成します。
=# CREATE INDEX idx2 ON book USING fulltextab((array[title, header, body, author])); =# SELECT title FROM book WHERE array[title, header, body, author] @@ '日本'; -- クエリ3 title ---------------- 日本国憲法 我輩は猫である Ludiaのすすめ (3 rows) =# SELECT title FROM book WHERE array[title, header, body, author] @@ '*W1 検索'; -- クエリ4 title ------------ 日本国憲法 (1 row)
配列型インデックスを用いると、クエリ3のように、検索が1つのみ実行されます。
クエリ1とクエリ3は同じ検索結果。クエリ3の方が高速です。
クエリ2とクエリ4は同じ検索結果。検索時間はほぼ等しいです。
また、この配列型インデックスを用いると、
以下のようにカラムごとの重み付け検索が可能です。
=# CREATE INDEX idx2 ON tab USING fulltexta((array[title, header, body, author])); =# SELECT *, pgs2getscore(ctid) AS score FROM tab WHERE array[title, header, body, author] @@ '*W1:10,2:3,3:1,4:10 日本' ORDER BY score DESC; -- クエリ5 title | score ----------------+------- 日本国憲法 | 14 我輩は猫である | 3 Ludiaのすすめ | 1 (3 rows)
この例では、titleを10、headerを3、bodyを1、authorを10に重み付けして、
検索してソートしてます。
(*W の書式は http://qwik.jp/senna/query.html を見てください。)
このように、OR検索ではマルチカラムインデックスより便利な
配列型インデックスはLudia1.4.0で登場します。
お楽しみに!
# 配列型インデックスはLudia1.3.1でもそれっぽく動きます・・・。