pg_bigm は、AnalyticDB for PostgreSQL がサポートするオープンソースのサードパーティ拡張機能です。この拡張機能は、2-gram の一般化逆インデックス(GIN インデックス)を作成することで、全文検索機能を提供し、検索処理を高速化します。
この拡張機能は、テキストから 2 文字のフラグメント(ビグラム)を抽出します。2 文字未満のフラグメントには、先頭または末尾に半角スペースが追加されます:
postgres=> SELECT show_bigm('full text search');
show_bigm
------------------------------------------------------------------
{" f"," s"," t",ar,ch,ea,ex,fu,"h ","l ",ll,rc,se,"t ",te,ul,xt}
(1 行)前提条件
開始する前に、以下の条件を満たしていることを確認してください。
弾力的ストレージモードで実行中の AnalyticDB for PostgreSQL インスタンス(V6.6.2.1 以降(V6.0)、または V7.0.6.1 以降(V7.0))
pg_bigm 拡張機能がインストール済みであること(詳細については、「拡張機能のインストール、更新、およびアンインストール」をご参照ください)
注意事項
GIN インデックスのキー列サイズ制限は 107,374,180 バイト(約 102 MB)です。この制限を超えるデータを挿入すると、メモリ不足エラーが発生します:
postgres=> CREATE TABLE t1 (description text); CREATE TABLE postgres=> CREATE INDEX t1_idx ON t1 USING gin (description gin_bigm_ops); CREATE INDEX postgres=> INSERT INTO t1 SELECT repeat('A', 107374181); ERROR: メモリ不足非 ASCII データを格納するデータベースでは、エンコーディングを UTF-8 に変更してください。現在のエンコーディングを確認するには、次の文を実行します:
SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = current_database();
拡張機能のインストール
AnalyticDB for PostgreSQL インスタンスの [拡張] ページに pg_bigm をインストールします。詳細については、「拡張のインストール、更新、およびアンインストール」をご参照ください。
インデックスの作成
gin_bigm_ops オペレータークラスを使用して、テーブルと GIN インデックスを作成します:
CREATE TABLE pg_tools (tool text, description text);
INSERT INTO pg_tools VALUES ('pg_hint_plan', 'ユーザーが PostgreSQL に対してオプティマイザヒントを指定できるツール');
INSERT INTO pg_tools VALUES ('pg_dbms_stats', 'ユーザーが PostgreSQL のプランナ統計情報を安定化できるツール');
INSERT INTO pg_tools VALUES ('pg_bigm', 'PostgreSQL で 2-gram 全文検索機能を提供するツール');
INSERT INTO pg_tools VALUES ('pg_trgm', 'PostgreSQL で 3-gram 全文検索機能を提供するツール');
-- 単一列インデックス
CREATE INDEX pg_tools_idx ON pg_tools USING gin (description gin_bigm_ops);
-- fastupdate を無効化した複数列インデックス
CREATE INDEX pg_tools_multi_idx ON pg_tools USING gin (tool gin_bigm_ops, description gin_bigm_ops) WITH (FASTUPDATE = off);全文検索の実行
インデックス化された列に対して LIKE クエリを実行します。pg_bigm は GIN インデックスを自動的に使用します:
postgres=> SELECT * FROM pg_tools WHERE description LIKE '%search%';
tool | description
---------+---------------------------------------------------------------------
pg_bigm | PostgreSQL で 2-gram 全文検索機能を提供するツール
pg_trgm | PostgreSQL で 3-gram 全文検索機能を提供するツール
(2 行)類似検索の実行
=% オペレーターを使用して、pg_bigm.similarity_limit で設定されたしきい値を満たす類似度を持つ文字列を検索します:
postgres=> SET pg_bigm.similarity_limit TO 0.2;
SET
postgres=> SELECT tool FROM pg_tools WHERE tool =% 'bigm';
tool
---------
pg_bigm
pg_trgm
(2 行)関数
likequery()
likequery(text) は、検索キーワードを LIKE で処理可能なパターン文字列に変換します。この関数は、キーワードを % で囲み、入力内の %、_、\ などの特殊文字をエスケープします:
postgres=> SELECT likequery('pg_bigm has improved the full text search performance by 200%');
likequery
-------------------------------------------------------------------
%pg\_bigm has improved the full text search performance by 200\%%
(1 行)
postgres=> SELECT * FROM pg_tools WHERE description LIKE likequery('search');
tool | description
---------+---------------------------------------------------------------------
pg_bigm | PostgreSQL で 2-gram 全文検索機能を提供するツール
pg_trgm | PostgreSQL で 3-gram 全文検索機能を提供するツール
(2 行)show_bigm()
show_bigm(text) は、文字列内のすべての 2-gram 要素を含む配列を返します:
postgres=> SELECT show_bigm('full text search');
show_bigm
------------------------------------------------------------------
{" f"," s"," t",ar,ch,ea,ex,fu,"h ","l ",ll,rc,se,"t ",te,ul,xt}
(1 行)bigm_similarity()
bigm_similarity(text, text) は、2 つの文字列の 2-gram 集合間の最大類似度を表す 0 ~ 1 の浮動小数点数を返します。値が 0 の場合は完全に類似していないことを意味し、1 の場合は同一であることを意味します。
この関数を使用する際は、以下の動作にご注意ください。
bigm_similarity()は大文字・小文字を区別します。'ABC'と'abc'の類似度は 0 です。2-gram アルゴリズムでは、短い文字列にスペースが追加されます。このため、
'ABC'と'B'の類似度は 0 ですが、'ABC'と'A'の類似度は 0.25 です。
postgres=> SELECT bigm_similarity('full text search', 'text similarity search');
bigm_similarity
-----------------
0.5714286
(1 行)
postgres=> SELECT bigm_similarity('ABC', 'A');
bigm_similarity
-----------------
0.25
(1 行)
postgres=> SELECT bigm_similarity('ABC', 'B');
bigm_similarity
-----------------
0
(1 行)
postgres=> SELECT bigm_similarity('ABC', 'abc');
bigm_similarity
-----------------
0
(1 行)pg_gin_pending_stats()
pg_gin_pending_stats(index) は、GIN インデックスの保留リスト内のページ数およびタプル数を返します。この関数は、fastupdate が有効(デフォルト)の場合に有用です。なぜなら、GIN インデックスは新しいエントリをメインインデックスにマージする前に、保留リストにバッチ処理するためです:
postgres=> SELECT * FROM pg_gin_pending_stats('pg_tools_idx');
pages | tuples
-------+--------
0 | 0
(1 行)fastupdate = off でインデックスを作成した場合、保留リストは存在しないため、この関数は常に 0 を返します:
CREATE INDEX ON your_table_name (your_column_name gin_bigm_ops) WITH (fastupdate = off);GUC パラメーター
pg_bigm は、以下の Grand Unified Configuration(GUC)パラメーターを公開しています。ワークロードに応じて適切に調整してください。
pg_bigm.last_update
読み取り専用。pg_bigm 拡張機能が最後に更新された日付です。
pg_bigm.enable_recheck
デフォルト: on
GIN インデックスから候補タプルを取得した後に、再検証(recheck)を実行するかどうかを制御します。デフォルト値の on のままにしてください。
このパラメーターの重要性: GIN 全文検索は 2 段階で動作します。まず、ビットマップ索引スキャンにより、2-gram の一致に基づいて候補タプルを取得します。次に、再検証(ヒープスキャン)により、各候補が LIKE パターンに実際に一致するかを確認します。これは、2-gram インデックスが誤検知を生じる可能性があるためです。enable_recheck を off に設定すると、このステップがスキップされ、不正確な結果が返される可能性があります。
pg_bigm.gin_key_limit
デフォルト: 0(すべての 2-gram 要素を使用)
全文検索クエリ実行時に使用される 2-gram 要素の最大数を設定します。デフォルト値の 0 は、検索キーワードのすべての 2-gram 要素を使用することを意味します。
変更が必要なケース: 極めて長い検索キーワードの場合、すべての 2-gram 要素を使用するとクエリの実行速度が大幅に低下する可能性があります。このパラメーターを小さな正の値に設定することで、使用する 2-gram 要素数を制限し、パフォーマンスを向上させることができます。ただし、要素数を減らすと、再検証フェーズでフィルター処理する必要のある誤検知候補の数が増加することにご注意ください。
pg_bigm.similarity_limit
=% 類似検索オペレーターにおける最小類似度しきい値を設定します。このしきい値を超える類似度を持つタプルのみが返されます。
変更が必要なケース: 類似検索クエリの結果が多すぎる場合(曖昧な一致が多い場合)は、この値を増加させて結果を絞り込みます。一方、検索語が短い、または精度が低い場合などは、この値を減少させて結果を広げます。
付録:オペレーターおよびインデックスオペレータークラス
オペレーター
| オペレーター | 戻り値の型 | 説明 |
|---|---|---|
text % text | ブール値 | 最初の文字列が 2 番目の文字列と類似している場合に true を返します。検索を高速化するために GIN インデックスを使用します。 |
text =% text | ブール値 | pg_bigm.similarity_limit で設定されたしきい値を、2 つの文字列間の類似度が満たす場合に true を返します。 |
インデックスオペレータークラス
| オペレータークラス | 説明 |
|---|---|
gin_bigm_ops | テキストを 2-gram 集合に変換し、GIN インデックスに格納します。 |
関数リファレンス
| 関数 | 戻り値の型 | 説明 |
|---|---|---|
likequery(text) | text | キーワードを % で囲み、特殊文字をエスケープすることで、LIKE 互換のパターン文字列に変換します。 |
show_bigm(text) | text[] | 入力文字列内のすべての 2-gram 要素を含む配列を返します。 |
bigm_similarity(text, text) | real | 2 つの文字列の 2-gram 集合間の最大類似度を表す 0 ~ 1 の浮動小数点数を返します。 |
pg_gin_pending_stats(index) | (pages int, tuples bigint) | 指定された GIN インデックスの保留リスト内のページ数およびタプル数を返します。 |