これはPGroonga 2.X用のドキュメントです。古いPGroongaを使っているならPGroonga 1.xのドキュメントを見てください。

PGroonga対pg_bigm

PostgreSQLはデフォルトではアルファベットベースではない言語の全文検索をサポートしていません。たとえば、日本語・中国語・韓国語といったアジアの言語の全文検索をサポートしていません。アジアの言語をサポートしたサードパーティーのモジュールがあります。PGroongaはそのうちのひとつです。他にもpg_bigmというモジュールがあります。textsearchのパーサーもあります。たとえば、zhparserは中国語用のパーサーで、textsearch_ja(メンテナンスされていません)は日本語用のパーサーです。

pg_bigmモジュールはpg_trgmモジュールと似ています。pg_trgmモジュールはデフォルトではアジアの言語をサポートしていませんが、pg_bigmはサポートしています。

このドキュメントはPGroongaとpg_bigmの違いを説明します。

特徴

各モジュールの特徴は次の通りです。

PGroonga

「recheck」する必要がないのでPGroongaの検索は高速です。

PGroongaは更新中の検索をブロックしないので更新中も高速に検索できます。PGroongaは更新中も検索性能を落としません。

PGroongaはアルファベットベースの言語とアジアの言語が混ざっている場合も高速です。PGroongaはデフォルトでN-gramベースの全文検索を使います。これはpg_bigmと似ています。なぜなら、pg_bigmは2-gram(N-gramのNが2のケース)を使っているからです。しかし、PGroongaは可変長サイズのN-gramを使っています。N-gramはアルファベットベースの言語では遅くなりがちです。これは、アルファベットの字種が少ないからです。字種はだいたい26(「a」から「z」までと他にいくつか)になります。字種が少ないと転置インデックスのポスティングリストが長くなりがちです。(転置インデックスに詳しくないとこの説明はピンとこないかもしれません。)PGroonga対textsearch対pg_trgmも参照してください。N-gramベースの全文検索であるpg_trgmが遅めなのがわかります。PGroongaは「私はPostgreSQLユーザーです。」というようにアルファベットベースの言語とアジアの言語が混ざっているときでもアルファベットベースの言語にはN-gramベースの全文検索ではなく単語ベースの全文検索を使います。

PGroongaは更新も高速です。

PGroongaはPostgreSQLに保存しているインデックス対象のテキストも保存しているのでインデックスサイズは大きいです。

PGroongaのインデックスはクラッシュセーフではありません。もし、クラッシュしてPGroongaのインデックスが壊れた場合はREINDEXを実行する必要があります。

pg_bigmモジュール

pg_bigmモジュールはクラッシュセーフです。なぜならGINを使っているからです。GINはクラッシュセーフです。

pg_bigmモジュールは大量のドキュメントがマッチして各ドキュメントが長い場合は遅いです。なぜならpg_bigmはインデックスを使った検索の後に「recheck」する必要があるからです。

概要

モジュール サポートしている言語 検索 更新 インデックスサイズ
PGroonga 全言語 速い 速い 大きい
pg_bigm 全言語 遅い 遅い 小さい

ベンチマーク

このセクションでは日本語版Wikipediaを使ったベンチマーク結果を示します。ベンチマークスクリプトはpostgresql.shにあります。

概要

以下は全文検索インデックス作成のベンチマーク結果の概要です。

インデックス作成時間

以下は全文検索インデックスのサイズのベンチマーク結果の概要です。

インデックスサイズ

以下は全文検索性能のベンチマーク結果の概要です。

全文検索性能

以下はpg_bigmが他のモジュールより約50倍遅いのでpg_bigmを除いた全文検索性能のグラフです。

pg_bigmを除いた全文検索性能

環境

以下はベンチマーク環境です。

CPU Intel(R) Xeon(R) CPU E5-2660 v3 @ 2.60GHz (24cores)
メモリー 32GiB
スワップ 2GiB
ストレージ SSD (500GB)
OS CentOS 7.2

バージョン

以下はソフトウェアのバージョンです。

PostgreSQL PGroonga pg_bigm
9.6.1 1.1.9 1.2-20161011

データ

以下は対象データの統計情報です。

サイズ 約5.9GiB
レコード数 約90万件
タイトルの平均バイト数 約21.6B
タイトルの最大バイト数 250B
本文の平均バイト数 約6.7KiB
本文の最大バイト数 約677KiB

データロード

以下はデータロードのベンチマーク結果です。全文検索モジュールには依存しません。なぜならどのインデックスもまだ作られていないからです。

経過時間 データベースサイズ
約5分 約5GB

以下はデータをロードするSQLです。

COPY wikipedia FROM 'ja-all-pages.csv' WITH CSV ENCODING 'utf8';

このCSVデータはja-all-pages.csv.xzからダウンロードできます。

以下はwikipediaテーブルを定義するSQLです。

CREATE TABLE wikipedia (
  id integer PRIMARY KEY,
  title text,
  text text
);

インデックス作成

以下は全文検索インデックス作成のベンチマーク結果です。

モジュール 経過時間 インデックスサイズ 備考
PGroonga 約19分 約9.8GB PGroongaはデータをコピーしてそれに対してインデックスを作成します。データはzlibで圧縮しています。インデックスだけのサイズは約6.4GBです。
pg_bigm 約33分 約4.2GB maintenance_work_mem2GBです。

PGroongaのインデックス定義は以下の通りです。

CREATE INDEX wikipedia_index_pgroonga ON wikipedia
 USING pgroonga (title, text);

pg_bigmのインデックス定義は以下の通りです。

CREATE INDEX wikipedia_index_pg_bigm ON wikipedia
 USING GIN (title gin_bigm_ops, text gin_bigm_ops);

全文検索

全文検索のベンチマーク結果は以下の通りです。

クエリー:「テレビアニメ」

モジュール 経過時間 ヒット数 相対経過時間
PGroonga 約65ミリ秒 約2万件 約1.1
Groonga 約38ミリ秒 約2万件 1
pg_bigm 約2.8秒 約2万件 約4.8

クエリー:「データベース」

モジュール 経過時間 ヒット数 相対経過時間
PGroonga 約49ミリ秒 約1万5千件 約1.6
Groonga 約31ミリ秒 約1万5千件 1
pg_bigm 約1.3秒 約1万5千件 約41

クエリー:「PostgreSQL OR MySQL」

モジュール 経過時間 ヒット数 相対経過時間
PGroonga 約2ミリ秒 316件 約2
Groonga 約1ミリ秒 316件 1
pg_bigm 約49ミリ秒 311件 約49

クエリー:「日本」

モジュール 経過時間 ヒット数 相対経過時間
PGroonga 約563ミリ秒 約53万件 約10
Groonga 約59ミリ秒 約53万件 1
pg_bigm 約479ミリ秒 約53万件 約8