BloGroonga

2017-04-29

PostgreSQL用高速日本語全文検索モジュールPGroonga(ぴーじーるんが) 1.2.0リリース

PostgreSQLで高速日本語全文検索をできるようにするPGroongaの1.2.0をリリースしました!

新規ユーザーの方は、PGroonga 1.0.0のリリースアナウンスのPGroongaについても参照してください。

ハイライト

今回のリリースのハイライトは次の通りです。

  • レプリケーション機能の改良

  • トークンフィルター・プラグインのサポート

  • PGroongaのインデックスの自動復旧機能の追加

  • 2.0.0へのスムーズな移行の準備

それぞれ説明します。

レプリケーション機能の改良

今回のリリースではレプリケーションまわりの機能を改良しています。

NULLを含むカラムでもレプリケーションできるようになりました。

データ同期のタイミングも増えました。これまではSELECT時のみ同期していましたが、INSERT時にも同期するようになりました。

Ubuntu 17.04とCentOS 6のパッケージでもレプリケーションできるようになったので、より使いやすくなっています。

レプリケーションの詳細は公式ドキュメント「レプリケーション」を参照してください。

トークンフィルター・プラグインのサポート

CREATE INDEX USING pgroongaでインデックスをつくるときにトークンフィルターとプラグインを指定できるようになりました。それぞれtoken_filterspluginsで指定します。

これによりチューニングの幅が広がりました。たとえば、英語のテキストを全文検索したい場合にステミング機能を使えるようになりました。使い方は公式ドキュメントを参照してください。

PGroongaのインデックスの自動復旧機能の追加

PostgreSQLを強制終了するとPGroongaのインデックスが壊れることがあります。滅多なことで強制終了するものではありませんが、せざるを得ない場合もあり、そのときに壊れることがあります。

pgroonga_checkモジュールを使うと起動時にPGroongaのインデックスをチェックし、壊れていたら自動で復旧できます。強制終了が起こり得る場合はこのモジュールを使ってみてください。

2.0.0へのスムーズな移行の準備

PGroonga 2.0.0では今よりもっと柔軟に検索できるようになる予定です。ただ、そのために現在の使い方と互換性がなくなる箇所があります。

互換性がなくなるとアップグレードが大変になるため、できるだけスムーズにアップグレードできるようにしたいものです。

そのために、今回のリリースから徐々に2.0.0と同じ使い方もできるようにしはじめました。2.0.0と同じ使い方に徐々に変更していくことでスムーズにアップグレードできるようになるだろうという寸法です。

具体的には以下の2.0.0での全文検索用の演算子を1.2.0でも使えるようにしました。

今後は1.xでも&@&?を使うようにしてください。これらを使っておけば変更なしに2.0.0でも動きます。%%@@は非推奨とします。

2.0.0は近いうちにリリースする予定ですが、2.0.0でも1.xの演算子を使えるようにするなど、できるだけスムーズにアップグレードできるようにする予定です。お楽しみに。

アップグレード方法

1.0以降のすべてのバージョンと互換性があります。アップグレードの「互換性がある場合」用の手順でアップグレードしてください。

おしらせ

PGroongaのサポートサービスを提供しています。インデックスや検索の設計方法に関するコンサルティングやトラブル時の調査、パフォーマンス改善・新機能追加などの技術支援など、PGroongaに関わるサポートが必要な場合はご相談ください。

まとめ

PGroongaの新しいリリースを紹介しました。インデックス破損の自動復旧が追加されたりしてどんどん使いやすくなっています。

ここで紹介したもの以外の変更点はリリースノートを参照してください。

PostgreSQLで高速に日本語全文検索をしたいという方はPGroongaを使ってガンガン検索してください!

2017-04-29

Groonga 7.0.2リリース

今日は肉の日ですね!

Groonga 7.0.2をリリースしました!

それぞれの環境毎のインストール方法: インストール

変更内容

今回のリリースでは、特定の条件下で reindex コマンドを使うとデータを失ってしまう不具合を修正しています。

主な変更点は以下の通りです。

  • reindexコマンドの実行によりデータが失われてしまう不具合を修正しました
  • Ubuntu 17.04 (Zesty Zapus)をサポートしました
  • 永続キャッシュをサポートしました
  • [in_records] 既存のテーブルを条件のパターンとして指定できるようになりました

reindexコマンドの実行によりデータが失われてしまう不具合を修正しました

今回のリリースでは、特定の条件下でreindexコマンドを使うとデータが失われてしまう不具合を修正しました。

インデックスだけが壊れてしまった場合、reindexを使って復旧することができます。しかし、今回見つかった不具合の発生条件を満たすと、無事だったデータを消してしまいます。

この不具合は、reindexコマンドが追加されたGroonga 5.1.0からの潜在的な不具合した。

テーブルにデータカラムがなくインデックスカラムのみある場合、そのテーブルは語彙表として使っていると判断し、テーブルのキーを全部消してから作り直すようにしていましたが、そのせいでデータを消してしまっていました。

例えば、次のようにすると問題を再現することが可能です。

> table_create User TABLE_HASH_KEY ShortText
[[0,1490948112.512871,0.004843950271606445],true]
> table_create Comment TABLE_NO_KEY
[[0,1490948112.517823,0.004474639892578125],true]
> column_create Comment user COLUMN_SCALAR User
[[0,1490948112.522444,0.00609898567199707],true]
> column_create User comment COLUMN_INDEX Comment user
[[0,1490948112.528664,0.009341239929199219],true]
> load --table Comment
> [
> {"user":"Mike"}
> ]
[[0,1490948112.538067,0.0004284381866455078],1]

> select User
[[0,1490948112.538533,0.0002899169921875],[[[1],[["_id","UInt32"],["_key","ShortText"],["comment","UInt32"]],[1,"Mike",1]]]]
> select Comment
[[0,1490948112.53886,4.744529724121094e-05],[[[1],[["_id","UInt32"],["user","User"]],[1,"Mike"]]]]

> reindex
[[0,1490948112.538933,0.02556586265563965],true]

> select User
[[0,1490948112.564538,5.91278076171875e-05],[[[0],[["_id","UInt32"],["_key","ShortText"],["comment","UInt32"]]]]]
> select Comment
[[0,1490948112.564621,3.457069396972656e-05],[[[1],[["_id","UInt32"],["user","User"]],[1,""]]]]

reindexした後の User テーブルと Comment テーブルのデータが失われていることがわかります。

Ubuntu 17.04 (Zesty Zapus)をサポートしました

今回のリリースでは、今月リリースされたUbuntu 17.04 (Zesty Zapus)をサポートしました。 PPA経由でインストールできます。

また、Ubuntu 12.04は4/28にEOLとなったため、サポートをやめています。

永続キャッシュをサポートしました

今回のリリースでは、永続キャッシュと呼ばれる仕組みをサポートしました。

GroongaのキャッシュはGroongaを終了すると消えてしまいます。再び起動しなおした場合、再度キャッシュを作り直すまでにはタイムラグが発生します。 永続キャッシュを使うと、そのタイムラグを短縮することができます。

groongaコマンドの場合

groongaコマンド実行時に --cache-base-path オプションを指定します。

このオプションには永続キャッシュを保存するパスを指定します。例えば、--cache-base-path=/dev/shm/groonga-cache を指定すると、 /dev/shm 直下に永続キャッシュファイルができます。この例だと次の2つのファイルが作成されます。

  • /dev/shm/groonga-cache.keys
  • /dev/shm/groonga-cache.values
groonga-httpdの場合

groonga-httpdの設定ファイル(/etc/groonga/groonga-httpd.conf)に以下の設定を追加します。

http {
  ...
  groonga_cache_base_path /dev/shm/groonga-httpd-cache;
  ...
}

serverやlocationディレティブごとに指定することもできます。ここで指定した永続キャッシュはワーカー間で共通です。従来のキャッシュの場合には、ワーカー毎にキャッシュを保持していました。永続キャッシュでは共通なので、あるワーカーではキャッシュされていたので速いけど、ほかのワーカーではキャッシュされていなかったので遅い、というようなことが起きなくなります。また、キャッシュ数の設定をワーカー毎にしなくてすむようになります。

注意事項について
  • メモリーファイルシステム上のパス(例:/dev/shm/xxxx)を必ず指定してください。ハードディスクなどディスクIOが遅い場合には、永続キャッシュを使用しても、その読み込みに時間がかかってしまうため、キャッシュを永続化する利点が薄れてしまいます。

  • 永続キャッシュにおいて、キャッシュ数の制御がまだ行えません。cache_limitは従来のキャッシュのみサポートしています。永続キャッシュのデフォルト設定値は100です。

  • 永続キャッシュを開けない場合は自動的に再作成するので問題ありませんが、クラッシュした場合はキャッシュファイルを削除してください。

[in_records] 既存のテーブルを条件のパターンとして指定できるようになりました

今回のリリースでは、既存のテーブルを条件のパターンとして指定するための in_records をサポートしました。 in_records を使うと複数のクエリーを1つのクエリーへとまとめることができるかもしれません。 これは、既存のテーブル内の各レコードがそれぞれ条件のパターンになる(複数の条件を指定できる)からです。

例えば、ログから特定のパターンのレコードを抽出することを考えてみましょう。 ログには、ユーザーとそれに紐づくタグ、時刻が記録されているとします。 サンプルとなるスキーマとデータは以下を使うことにします。

table_create Users TABLE_HASH_KEY ShortText
table_create Tags TABLE_HASH_KEY ShortText

table_create Reports TABLE_NO_KEY
column_create Reports user COLUMN_SCALAR Users
column_create Reports tag COLUMN_SCALAR Tags
column_create Reports day COLUMN_SCALAR Time

table_create Logs TABLE_NO_KEY
column_create Logs user COLUMN_SCALAR Users
column_create Logs tag COLUMN_SCALAR Tags
column_create Logs time COLUMN_SCALAR Time

load --table Reports
[
{"user": "alice", "tag": "tag1", "day": "2017-04-18 00:00:00"},
{"user": "alice", "tag": "tag1", "day": "2017-04-19 00:00:00"},
{"user": "david", "tag": "tag2", "day": "2017-04-20 00:00:00"},
{"user": "david", "tag": "tag3", "day": "2017-04-21 00:00:00"}
]
  
load --table Logs
[
{"user": "alice", "tag": "tag1", "time": "2017-04-18 11:22:33"},
{"user": "alice", "tag": "tag1", "time": "2017-04-20 11:22:33"},
{"user": "bob",   "tag": "tag1", "time": "2017-04-19 11:22:33"},
{"user": "david", "tag": "tag1", "time": "2017-04-19 11:22:33"},
{"user": "david", "tag": "tag2", "time": "2017-04-20 11:22:33"}
]

Logs がログを記録しているテーブルです。特定のログに tag がつけられています。 特定のユーザーとタグがつけられているある日のログのみを抽出したい、というのを実現しようとすると、クエリはどんどん複雑になっていきます。 けれども今回追加された in_records を使うと条件のパターンを既存のテーブルへとまとめることができるのでクエリーを1つにすることができます。

select Logs \
  --filter 'in_records(Reports, \
                       user, "==", "user", \
                       tag, "==", "tag", \
                       time_classify_day(time), "==", "day")'

上記の例では条件のパターンを Reports に保存された4つのレコードで表現しています。 サンプルでは Reports テーブルしか使っていませんが、ここに指定しているテーブルを替えるだけで、条件のパターンのバリエーションを簡単に切り替えることもできます。

さいごに

7.0.1からの詳細な変更点は7.0.2リリース 2017-04-29を確認してください。

それでは、Groongaでガンガン検索してください!

2017-03-29

Groonga 7.0.1リリース

今日は肉の日ですね!

Groonga 7.0.1をリリースしました!

それぞれの環境毎のインストール方法: インストール

変更内容

主な変更点は以下の通りです。

  • CentOS 5のサポートをやめました
  • データベースの肥大化対策が入りました
  • [実験的] ヒット数が少なそうな条件から並べ替えて検索できるようになりました

CentOS 5のサポートをやめました

3/31でCentOS 5がEOLとなるため、今月のリリースからCentOS 5向けのパッケージの提供をやめました。

CentOS 6もしくはCentOS 7でのパッケージの提供は継続するので、そちらへの移行をおすすめします。

データベースの肥大化対策が入りました

6.1.4のリリースにおいて、インデックスを更新する際、非自然言語だと遅い問題を改善しました。しかし、その結果副作用として自然言語ではインデックスサイズが増える問題がありました。トークナイザーが語彙表に指定されていたら旧アルゴリズムを適用することで問題を修正しています。

全文検索をする場合、トークナイザーを指定する使い方が通例なので、以下のように2つのアルゴリズムを使い分けるようにしています。

  • 語彙表にトークナイザーの指定あり(従来のアルゴリズム適用によりインデックスの肥大化の問題がない)
  • 語彙表にトークナイザーの指定なし(非自然言語用のアルゴリズム適用により従来アルゴリズムの欠点であった性能劣化がない)

どれくらい肥大化していたかというと、5GくらいのDBで7GBくらいに増えるケースがありました。

6.1.4以降がその影響を受けます。静的更新の場合には問題なく、動的に更新したときに増加が問題になっていました。以下は変更前後のテストケースでどれくらい違いがあるかを示しています。

動的更新と静的更新によるデータベースサイズの違い

[実験的] ヒット数が少なそうな条件から並べ替えて検索できるようになりました

ヒット件数が少ない条件から絞り込むことで高速に検索できることに着目し、条件を自動的に並べ替える機能を追加しました。

  • A (件数が多い) && B (件数が少ない)

上記のような場合、以下のようにすると検索が速いです。

  • B (件数が少ない) && A (件数が多い)

これはよく知られたやりかたですが、上記を実現しようとすると、従来はアプリケーション側でクエリをいい感じに並べ替える最適化をあれこれと頑張る必要がありました。

有効にするには環境変数 GRN_ORDER_BY_ESTIMATED_SIZE_ENABLE=yes を設定します。 この環境変数が有効な場合、どれくらいヒットしそうかを推定するGroongaのAPIを活用して条件の並べかえを行うようになります。

Groongaで最適化を自動的に行うことができるようになりますが、この機能は実験的なためデフォルトでは無効です。

さいごに

7.0.0からの詳細な変更点は7.0.1リリース 2017-03-29を確認してください。

それでは、Groongaでガンガン検索してください!

2017-02-09

Groonga 7.0.0リリース

今日は肉の日ですね!

Groonga 7.0.0をリリースしました!メジャーバージョンアップです!メジャーバージョンアップですが互換性は壊れていないので安心してアップグレードしてください!

それぞれの環境毎のインストール方法: インストール

変更内容

主な変更点は以下の通りです。今回のリリースも盛りだくさんです!

  • DBのメタデータを不必要に更新しないようにしました。selectコマンド使っているだけなのにロックされたままになってしまわないようになります。(ロック残留の問題が発生しない)
  • lock_clear でメタデータのロックを削除できるようになりました。(以前のバージョンを使っていて、selectコマンド使っているだけなのにロックされたままになってしまった場合には、Groongaをアップグレードしてから lock_clear するとロックを解除できる)
  • CentOS 7でも TokenTokenFilterStem が使えるようになりました。(CentOS 7でもステミング機能が使える)
  • load --output_errors yesオプションを指定すると、なぜ特定のレコードがloadできなかったかもわかるようになりました。(特定のレコードがloadされない問題の特定に役立つ)

今回も新機能や不具合修正の多くに@naoa_yさんがパッチを提供してくれました。ありがとうございます!

お知らせ

今月は、Groonga Meatup 2017の他にも以下のイベントが予定されています。

興味があるイベントがあればぜひご参加ください!

さいごに

6.1.5からの詳細な変更点は7.0.0リリース 2017-02-09を確認してください。

変更点を確認すると、6.xシリーズのGroongaは着実に成長してきたことがわかります。これまで気になっていたけど触っていなかった人は、ぜひ、このメジャーバージョンアップを期にGroongaを触ってみてください。

それでは、今年もGroongaでガンガン検索してください!

2017-01-23

Groonga 6.1.5リリース

Groonga 6.1.5をリリースしました。6.1.4のバグフィックスリリースです。6.1.2、6.1.3、6.1.4をお使いの方はアップグレードをお願いします。

それぞれの環境毎のインストール方法: インストール

変更内容

Groonga 6.1.2で導入したAND検索時の高速化に問題があったため修正しました。マッチするべきレコードがマッチしないことがあります。インデックスは壊れていないため、インデックスの再構築は必要ありません。アップグレードするだけで直ります。

さいごに

繰り返しになりますが、6.1.2、6.1.3、6.1.4をお使いの方はアップグレードをお願いします。

6.1.4からの詳細な変更点は6.1.5リリースを確認してください。