これはPGroonga 1.X用のドキュメントです。新しいPGroongaを使っているならPGroonga 2.xのドキュメントを見てください。
PostgreSQLはデフォルトではアルファベットベースではない言語の全文検索をサポートしていません。たとえば、日本語・中国語・韓国語といったアジアの言語の全文検索をサポートしていません。アジアの言語をサポートしたサードパーティーのモジュールがあります。PGroongaはそのうちのひとつです。他にもpg_bigmというモジュールがあります。textsearchのパーサーもあります。たとえば、zhparserは中国語用のパーサーで、textsearch_ja(メンテナンスされていません)は日本語用のパーサーです。
pg_bigmモジュールはpg_trgmモジュールと似ています。pg_trgmモジュールはデフォルトではアジアの言語をサポートしていませんが、pg_bigmはサポートしています。
このドキュメントはPGroongaとpg_bigmの違いを説明します。
各モジュールの特徴は次の通りです。
「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モジュールはクラッシュセーフです。なぜならGINを使っているからです。GINはクラッシュセーフです。
pg_bigmモジュールは大量のドキュメントがマッチして各ドキュメントが長い場合は遅いです。なぜならpg_bigmはインデックスを使った検索の後に「recheck」する必要があるからです。
モジュール | サポートしている言語 | 検索 | 更新 | インデックスサイズ |
---|---|---|---|---|
PGroonga | 全言語 | 速い | 速い | 大きい |
pg_bigm | 全言語 | 遅い | 遅い | 小さい |
このセクションでは日本語版Wikipediaを使ったベンチマーク結果を示します。ベンチマークスクリプトはpostgresql.shにあります。
以下は全文検索インデックス作成のベンチマーク結果の概要です。
PGroongaが一番速いモジュールです。
pg_bigmはPGroongaよりも約73%遅いです。
以下は全文検索インデックスのサイズのベンチマーク結果の概要です。
pg_bigmが一番小さいモジュールです。
PGroongaはpg_bigmよりも約2.3倍大きいです。
以下は全文検索性能のベンチマーク結果の概要です。
pg_bigmの全文検索性能は他のモジュールよりも約50倍遅いです。ただし、「日本」(クエリーが2文字のケース)は遅くありません。
PGroongaとGroongaの全文検索性能は似ています。ただし、「日本」(ヒット数が多いケース)ではGroongaの方が10倍高速です。
以下はpg_bigmが他のモジュールより約50倍遅いので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_mem は2GB です。 |
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);
全文検索のベンチマーク結果は以下の通りです。
「Groonga」はpgroonga.command('select ...')
の結果です。pgroonga.command
も参照してください。
「相対経過時間」は対象の経過時間と最速のケースの経過時間の比率です。大きいほど遅いです。
クエリー:「テレビアニメ」
モジュール | 経過時間 | ヒット数 | 相対経過時間 |
---|---|---|---|
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 |