- PostgreSQLの標準Full-Text Search(FTS)は遅いという認識があるが、適切に最適化すれば非常に高速に動作する
- NeonのブログではRustベースの
pg_search拡張と標準FTSを比較し、後者は遅いと主張している
- しかしこの比較は、PostgreSQL FTSに不可欠な基本的な最適化作業が欠けた状態で行われた可能性が高い
- 本記事では、標準FTS設定に簡単な最適化を施すだけで50倍の性能向上が可能であることを数値で示している
ベンチマーク設定の概要
- 1,000万件のログデータを持つテーブルをベースにテストを実施
CREATE TABLE benchmark_logs (
id SERIAL PRIMARY KEY,
message TEXT,
country VARCHAR(255),
severity INTEGER,
timestamp TIMESTAMP,
metadata JSONB
);
- 問題のクエリ構造:
SELECT country, COUNT(*)
FROM benchmark_logs
WHERE to_tsvector('english', message) @@ to_tsquery('english', 'research')
GROUP BY country
ORDER BY country;
to_tsvector()をクエリ内で実行 → 非常に非効率
- GINインデックスがあっても適切に活用されない
テスト環境(標準設定を再現)
性能低下要因 1: リアルタイムのtsvector計算
性能低下要因 2: GINインデックスのfastupdate=on設定
性能向上の数値: 50倍以上の改善
- 最適化前: 約41.3秒 (41,301 ms)
- 最適化後: 約0.88秒 (877 ms)
- 約50倍の性能向上を示した
- 並列処理数が少ない環境でもこの性能を達成可能
ts_rankの性能は実際に遅いことがある
ts_rankまたはts_rank_cdはすべての結果を評価してから並べ替えるため、相対的に遅くなることがある
- 特に大量の結果を扱う場合はCPU/IO負荷が大きい
高度なランキング機能: VectorChord-BM25拡張
- 並べ替えの精度と速度が重要な場合は、専用拡張を使う方が効果的
- VectorChord-BM25はPostgreSQL向け拡張で、BM25アルゴリズムベースのランキング評価機能を提供
- Elasticsearchより3倍速いという報告もある
VectorChord-BM25の利点
- BM25アルゴリズム: TF-IDFより進化した検索ランキングアルゴリズム
- 専用インデックス形式: Block WeakAnd など、高速検索に最適化
bm25vector型を提供: トークン化された表現を保存
- 検索精度と速度の両方を向上
結論: PostgreSQL標準FTSも十分に速い
tsvectorカラムと適切なGINインデックス(fastupdate=off)を使えば、標準FTSでも非常に高速な検索が可能
- 性能比較は最適化された基準で行われるべき
- 高度なランキング機能が必要な場合は、VectorChord-BM25のような拡張ツールの活用を検討できる
- 核心メッセージ: ツールが遅いのではなく、設定が問題である可能性がある
3件のコメント
おかげでクエリのチューニングをしました。
Hacker Newsの反応、怖いですね…「1000万件? 冗談でしょ?」
Hacker News の意見
pg_search のメンテナーとして言うと、Postgres のドキュメントによれば、Neon/ParadeDB の記事とここで使われている戦略はいずれも有効な代替案として提示されている
tsvector をリアルタイムで計算するのは大きなミスだ
何でもかんでも Postgres に入れようとする傾向は理解できない
Postgres ネイティブの全文検索実装をもっと多く見られるのはうれしい
説明計画がないので、何が起きているのか理解しづらい
数年前、ネイティブ FTS を使いたかったが失敗した
pg_search と vchord_bm25 拡張の RPM/DEB をパッケージした
多くのチームが Elasticsearch や Meilisearch にそのまま移行するのを見てきた
1,000 万件のレコードはおもちゃのデータセットだ
2008 年ごろに初めて pg の全文検索を使った