PGroongaのインデックスを常に使う方法。
PGroongaはJSON(B)に対しても全文検索できるのが便利ですが、レコード数が少ないとこんな感じで困ったことになる。
チュートリアルにあるサンプルスキーマとデータを投入した状態で、
test=# SELECT record FROM logs WHERE record @@ 'paths @ ".code" && number >= 200 && number < 300'; ERROR: pgroonga: operator @@ is available only in index scans
レコード数が少ないので全件舐めたほうが速いからプランナがインデックスを使おうとせずにこうなる。
test=# explain SELECT record FROM logs WHERE record @@ 'paths @ ".code" && number >= 200 && number < 300'; QUERY PLAN -------------------------------------------------------------------------------- Seq Scan on logs (cost=0.00..26.38 rows=655 width=32) Filter: (record @@ 'paths @ ".code" && number >= 200 && number < 300'::text) (2 rows)
チュートリアルにあるとおり、
SET enable_seqscan = off;
すれば動くけど、本番でこれやるのはちょっとどうかと。かと言って、レコード数が増えてきてからPGroongaを使うようにアプリケーションを改修するっていうのも乗り気がしない。最初から@@演算子を使ったクエリを書きたい。
ってことでどうするか。要は常にインデックスを使うようにすればいいので、pg_hint_planを使う。
インストールした上で、クエリにヒント句を足してやるだけ。
test=# /*+ IndexScan(logs) */ SELECT record FROM logs WHERE record @@ 'paths @ ".code" && number >= 200 && number < 300'; record ---------------------------------------------------------------------------------------------- {"code": 200, "host": "www.example.com", "tags": ["web", "example.com"], "message": "GET /"} (1 row)
これでレコードが1つしかなかろうが常にインデックスが使用され、@@演算子を使ったクエリが常に通るようになる。