[pgsql-jp: 37953] インデックスGIN利用時tsearch2 でのNOT検索エラー(PostgreSQL v8.2.1)

kazu koza kosakamarines @ gmail.com
2007年 1月 18日 (木) 21:26:44 JST


コサカと申します。

ITProの新しいインデックスGINとtsearch2を組み合わせた全文検索の記事を読み
面白そうだと思い、実際に動作検証を行ってみました。
(http://itpro.nikkeibp.co.jp/article/COLUMN/20061122/254458/)

■テスト環境
OS CentOS4.4
DB PostgreSQL-8.2.1 + tsearch2
tsearch2はPostgreSQLのcontribからインストール

■PostgreSQLの初期化
#initdb --no-locale --encoding=EUC_JP

■テーブルの作成とデータ登録
#createdb test
#psql -l
  Name     | Owner     | Encoding
-----------+-----------+----------
 postgres  | postgres  | EUC_JP
 template0 | postgres  | EUC_JP
 template1 | postgres  | EUC_JP
 test      | postgres  | EUC_JP

#psql -f /usr/local/pgsql/share/contrib/tsearch2.sql -d test

#psql test

#CREATE TABLE sample(message TEXT,
                     idxfti TSVECTOR);

#CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON sample
 FOR EACH ROW EXECUTE PROCEDURE tsearch2(idxfti, message);

#CREATE INDEX idxfti_idx ON sample USING gin(idxfti);

#INSERT INTO sample(message) VALUES('test message');

■データの確認とNOT検索の実行
データは1件しかなく、NOT検索すれば1件もマッチしないという結果になるだろうと予測していたのですが・・・。

#SELECT * FROM sample;
   message    |       idxfti
--------------+---------------------
 test message | 'test':1 'messag':2

#SELECT * FROM sample WHERE idxfti @@ to_tsquery('!test');
ERROR:  Query requires full scan, GIN doesn't support it
#

クエリープランでは「full scan」が選択されたが、GINはサポートしていないよ?
というような内容のエラーが帰ってきました。
full scanをサポートしない?という意味がよくわからなかったのですがとりあえず
以下を実行し(デフォルトONと認識していますので意味がないと思いますが)

#SET enable_indexscan TO on;
#SET enable_bitmapscan TO on;

再度同じコマンドを実行してみたところ
#SELECT * FROM sample WHERE idxfti @@ to_tsquery('!test');
ERROR:  Query requires full scan, GIN doesn't support it

やはりエラーとなりました。
選択したプランがおかしいのかはよくわかりませんが、ANALYZEを実行してみたところ
#ANALYZE;
#SELECT * FROM sample WHERE idxfti @@ to_tsquery('!test');
 message | idxfti
---------+--------
(0 rows)

思っていた回答をしました。

ちなみにインデックスをGiSTで作成した場合は
とくにANALYZEを実行しなくてもエラーは発生しません。
#CREATE INDEX idxfti_idx ON sample USING gist(idxfti);

#SELECT * FROM sample;
   message    |       idxfti
--------------+---------------------
 test message | 'test':1 'messag':2

#SELECT * FROM sample WHERE idxfti @@ to_tsquery('!test');
 message | idxfti
---------+--------
(0 rows)

エラー内容がどこに起因するのか調べていたところ、tsearch2のソースの以下でエラーになることがわかったのですが、ここでどういった処理をしているかがわからずに足踏み状態となってしまいました。

ginidx.c 73行目〜
	item = clean_NOT_v2(GETQUERY(query), &len);
	if(!item)
	 elog(ERROR, "Query requires full scan, GIN doesn't support it")

query_cleanup.c 169行目〜
	ITEM *
	clean_NOT_v2(ITEM * ptr, int4 *len)
	{
	  NODE *root = maketree(ptr);
	  return plaintree(clean_NOT_intree(root), len);
	}

さらに調べていけば原因がわかるような気もするのですが、そもそもソースの問題ではなく
tsearch2の使い方が悪いんでしょうか?
でも特に難しいクエリーは発行していないのですが・・・。

皆様の見解をお聞かせいただければと思います。
よろしくお願いします。



pgsql-jp メーリングリストの案内