HAYASHI Kentaro
hayas****@clear*****
2014年 11月 29日 (土) 11:57:26 JST
林です。 今日はいい肉の日(11/29)、全文検索エンジンGroongaを囲む夕べ5の開催日ですね。 Groonga 4.0.8をリリースしました! http://groonga.org/ja/docs/news.html#release-4-0-8 それぞれの環境毎のインストール方法はこちらを見てください。 http://groonga.org/ja/docs/install.html 今回のリリースの主なトピックは次の通りです。 * [実験的] 逐次検索への自動切り替えのサポート (in_values/between) * [実験的] 複数のキーによるドリルダウンのサポート * [実験的] range_filterコマンドのサポート * groonga-httpdがデフォルトのHTTPサーバーになりました * [告知] Groonga Advent Calendar 2014はじまるよ! ○ [実験的] 逐次検索への自動切り替えのサポート(in_values/between) 今回のリリースでは、逐次検索への自動切り替えのサポート(in_values/between)を追加しました。 逐次検索への自動自動切り替えがどういうことか簡単に説明します。 例えば、--filterで絞り込んでからさらに&& in_values()で絞り込むとします。 通常、インデックスが使えるならインデックスを使って効率良く検索し、使えない場合には 逐次検索をしてマッチしたもので絞り込んでいきます。 インデックスが使える場合には、&& in_values()で絞り込み対象となるレコード数が だいたいどれくらいかが事前にわかっているので、追加で絞り込む前と インデックスを使って検索する対象となるレコードの比率を求めます。 (A) --filterで1000件に絞り込んだ && in_value()の対象となるレコード数が5万件 1000/50000 = 0.02 (B) --filterで1000件に絞り込んだ && in_value()の対象となるレコード数が50万件 1000/500000 = 0.002 (A)の場合は20%とそこそこ比率が高めです。一方(B)の場合は2%と大分小さいです。 そこで、(B)のときにインデックスを使わずに逐次検索してマッチしたものを返すのと (B)のときに50万件が対象となるインデックスを使って検索するのとどちらがコストが高いか という話になります。適切な閾値を下回る(対象となるデータ件数が十分少ない)のであれば 逐次検索したほうが速そうですね、というところがポイントです。 この機能はデフォルトで有効になっていて、閾値が0.01になっています。 そのため上記の(A)の場合には適用しませんが、(B)のときには逐次検索を試みます。 なおデフォルトの閾値は暫定的なもので、将来変更される可能性があります。 また、必ずしもすべてのケースで確実に高速化が見込めることを保証できているわけではありません。 そのため、この挙動は環境変数で変更することができるようになっています。 in_values()の場合: # 逐次検索をしない GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO=-1 # 比率の閾値を0.02にする GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO=0.02 between()の場合: # 逐次検索をしない GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO=-1 # 比率の閾値を0.02にする GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO=0.02 試してみて閾値はこれくらいに設定するのがウチの場合はよかった、など フィードバックをもらえると嬉しいです。 in_values(まだドキュメント化が追いついていない)やbetweenの詳細は 次のURLを参照してください。 http://groonga.org/ja/docs/reference/functions/in_values.html http://groonga.org/ja/docs/reference/functions/between.html ○ [実験的] 複数のキーによるドリルダウンのサポート 今回のリリースでは、複数のキーによるドリルダウンのサポートを追加しました。 これにより、大項目、中項目、小項目といった項目でグループ化した結果を 簡単に取得することができるようになりました。これまでは1つのキーしか サポートしていなかったので、そういったことをやるにはアプリケーション側で 頑張らないといけませんでした。 実際にどんな感じに使えるのか説明します。 サンプルとして使うスキーマは次のとおりです。 table_create Tags TABLE_PAT_KEY ShortText table_create Memos TABLE_HASH_KEY ShortText column_create Memos tag COLUMN_SCALAR Tags column_create Memos date COLUMN_SCALAR Time これに次のようなデータを投入します。 load --table Memos [ {"_key": "Groonga is fast!", "tag": "Groonga", "date": "2014-11-16 00:00:00"}, {"_key": "Mroonga is fast!", "tag": "Mroonga", "date": "2014-11-16 00:00:00"}, {"_key": "Groonga sticker!", "tag": "Groonga", "date": "2014-11-16 00:00:00"}, {"_key": "Rroonga is fast!", "tag": "Rroonga", "date": "2014-11-17 00:00:00"}, {"_key": "Groonga is good!", "tag": "Groonga", "date": "2014-11-17 00:00:00"} ] データの準備ができたら実際にドリルダウンしてみましょう。 クエリはこんなふうに書きます。 select Memos \ --command_version 2 \ --drilldown[tag].keys tag,date \ --drilldown[tag].output_columns _key[0],_key[1],_nsubrecs ドリルダウンの構文がこれまでと違いますね。 キーの指定は--drilldown[LABEL].keysになりました。 また、出力対象の指定も--drilldown[LABEL].output_columnsになっています。 --drilldown[tag].output_columns _key[0],_key[1],_nsubrecs output_columnsはちょっと見慣れない_key[N]がありますね。 これは、keysに指定したどちらのキーの値をとってくるかを指示するものです。 そのため、上記クエリの場合は _key[0]でtagカラムのレコード値をとってくる、 _key[1]でdateカラムのレコードの値をとってくるという意味になります。 _nsubrecsはグループ化した件数です。 返ってきた結果を抜きだすとこんな感じになります。 { "tag": [ [ 4 ], [ [ "_key[0]", null ], [ "_key[1]", null ], [ "_nsubrecs", "Int32" ] ], [ "Groonga", 1416063600.0, 2 ], [ "Mroonga", 1416063600.0, 1 ], [ "Rroonga", 1416150000.0, 1 ], [ "Groonga", 1416150000.0, 1 ] ] } ドリルダウンによってtagがGroongaであるもののうち、時刻が重複しているものが2つ あることがわかります。 大事なポイントがもう一つあります。 クエリに--command_version 2を付けるのを忘れないでください。 これは従来の構文を拡張しているためです。 ○ [実験的] range_filterコマンドのサポート 今回のリリースでは、range_filterコマンドのサポートを追加しました。 これはselectの簡易版で、条件を限定して高速化したコマンドです。 selectではマッチした件数を一緒に返しますが、 range_filterではそれをやらないというのがポイントです。 ただし、必要なデータが取得できた時点で走査を打ち切る特性から drilldownのようなグループ化して結果を返すものには適用できません。 マッチしたものすべてをあらかじめ知っておかないといけないからです。 そのため、ランキングの上位N件だけを取得したいときなど 全体の件数までは知らなくていいような検索に向いています。 ドキュメント化がまだ追いついていないのですが、詳細は次のURLで公開します。 http://groonga.org/ja/docs/reference/commands/range_filter.html ○ groonga-httpdがデフォルトのHTTPサーバーになりました これまで、GroongaのHTTPサーバーはgroonga-server-httpパッケージをまずは 使ってね、というスタンスだったのでした。 ただ、HTTPサーバーのパッケージが複数あるのはわかりにくいというのと groonga-httpdが登場してそれなりに経つということで、パッケージは groonga-httpdに一本化することにしました。 groonga-server-httpをアップデートするとgroonga-httpdに きりかわるようになっています。 groonga-server-httpとgroonga-httpdではたくさんの違いがあります。 どう違うかについては、比較のページを用意しているのでそちらを確認してください。 http://groonga.org/ja/docs/server/http/comparison.html groonga-httpd特有のディレクティブについては、次のページで説明しています。 http://groonga.org/ja/docs/reference/executables/groonga-httpd.html ○ [告知] Groonga Advent Calendar 2014はじまるよ! 昨年、お試しとばかりにGroonga Advent Calendar 2013を実施したところ、 みなさんのおかげでたくさんの有用な情報をあつめることができました。 http://qiita.com/advent-calendar/2013/groonga 先日Groonga Advent Calendar 2014のお誘いメールがありましたが http://sourceforge.jp/projects/groonga/lists/archive/dev/2014-November/002968.html 今年もGroonga Advent Calendar 2014をやります。 http://qiita.com/advent-calendar/2014/groonga Groonga関連のちょっとした情報をまとめてみませんか? 早速参加登録してくれた人の内容はこんな感じです。楽しみですね。 12/1 Groonga 2014年現在のGroongaの最新情報を紹介します!by groonga 12/2 Rroonga と Vue.js で単機能検索ページ制作入門っぽいやつを書きますby polamjag 12/3 RailsでMroongaを活用する際のTipsを書きます。by tamano 12/4 Groongaのデータベースの中を見たいときに、自分が使っているやり方を書いてみたいと思います。by myokoym 12/5 grn_miniの使い方についてby ongaeshi 12/8 ドリルダウンとベクターカラムのドリルダウンとマルチドリルダウンの使い道について考えるby naoa 12/12 Mroonga with MySQL Fabric(仮)by yoku0825 12/14 Groonga on ARMな話(仮)を書くはず。by kenhys 12/15 編集距離とトークンフィルターを使ったタグの名寄せ処理の挑戦(できるか知らない)by naoa 12/21 Nroongaに触れてみるby myokoym 今なら12/6,12/7,12/9,12/10,12/11,....と空きがあるので、お好きな日を選び放題ですよ。 まずは、参加登録してみてください。ネタに困った人は過去のMLの投稿をまとめるというのもいいと思います! http://qiita.com/advent-calendar/2014/groonga ○ 変更点 さて、4.0.7からの変更点は以下の通りです。 http://groonga.org/ja/docs/news.html#release-4-0-7 改良 * [deb] Travis-CIの動作環境であるUbuntu 12.04のサポートを再び有効にしました。 * [mruby] デバッグ用途に "pp" をサポートしました。 内部のオブジェクトをよりわかりやすく表示できるようになりました。 * 全文検索のクエリで --match_columns と --query の組み合わせでインデックスが使えず 逐次検索になる場合、--match_columns に指定されているカラムが1つだけなら検索できるようにしました。 [groonga-dev,02902] [篠田さんが報告] * [実験的] in_values で逐次検索に自動的に切り替えられるようにしました。逐次検索のほうがインデックスを 使った検索よりも速い場合があります。たとえば、絞り込む前のレコードの件数が、さらに in_values と AND で絞り込むのに使うレコード数に比べてだいぶ少ないような場合です。このとき GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO 環境変数の値が逐次検索をするのか、インデックスを使って検索をするのかの閾値として使われます。 * [mruby] 相対パスのスクリプトの読み込みをサポートしました。 * mrubyが有効な場合にクエリオプティマイザーのテストを簡単に書けるようになりました。 * トークンフィルターを使った静的なインデックス作成をサポートしました。 [GitHub#239] [村上さんがパッチ提供] * [実験的] between でも逐次検索への自動切り替えをサポートしました。 GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO 環境変数を閾値として使います。 基本的な考え方は GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO と同じです。 * [実験的] select コマンドで複数のキーを指定してドリルダウンできるようになりました。 この機能のために構文を拡張しています。新しいドリルダウンの構文では --drilldown[LABEL1].keys COLUMN1,COLUMN2 をキーの指定に使います。 output_columnsの場合は --drilldown[LABEL1].output_columns _value.COLUMN1,_value.COLUMN2,_nsubrecs です。 以前のバージョンでは、複数のキーによるドリルダウンを実現するにはクライアントアプリケーション側でそのような機能を 実装するしかありませんでした。ドリルダウンでグループ化されたレコードのキーを参照するには、 _key[N] を使います。 * インデックスなしでも '参照型のカラム @ "query"' で検索できるようになりました。 * [実験的] range_filter コマンドを追加しました。たいていの場合、特定の範囲のレコードを取得するなら select コマンドよりも速いです。これはマッチしたレコード数を返さないので、そのためのレコードの走査が不要なためです。 ただし、ドリルダウンをサポートしていないなどの制限があります。 range_filter は特定の範囲の最初の N レコードを必要とするランキングなどの用途に向いています。 * [windows] Windows上でも groonga-httpd が使えるようになりました。 * ドリルダウンでベクター型のカラムをサポートしました。 * [deb] デフォルトのHTTPサーバーパッケージを groonga-httpd にしました。 groonga-server-http は非推奨です。ただし、 groongaコマンド のHTTPサーバー機能自体はまだ使えます。 もし従来のような簡易HTTPサーバーを使いたいなら、適宜引数を groongaコマンド へとコマンドライン経由で渡します。 * WindowsのCI環境であるAppVeyor向けの設定ファイルを追加しました。 [groonga-dev,02970,02981] [畑ケさんがパッチ提供] 修正 * [doc] table_create の重複した実行例を修正しました。[GitHub groonga.org#14] [横山さんが報告] * ネストしたインデックスで X._key に対する全文検索をしたときに空の結果を返す不具合を修正しました。 * BSD で仕様が厳密になった mkostemp(3) に対して渡しているフラグを修正しました。 [GitHub#240] [Kuriyamaさんがパッチ提供] * select コマンドが 誤った値の型(table)をインデックスカラムの値の型として返す不具合を修正しました。 UInt32 を返すように修正しています。この変更はレスポンスのヘッダー部分にのみ影響します。これにより検索結果は変りません。 * Time型と文字列型の比較( < , <= , > , >= , != )が誤った結果を返す不具合を修正しました。 * "x*" といった一文字の前方一致検索が行えない不具合を修正しました。[GitHub#242] [村上さんがパッチ提供] * ShortText 型の値に対するドリルダウンを --filter と一緒に使ったときにメモリリークしていたのを修正しました。 * "DDL:set_token_filters" のログに "," が抜けていたのを修正しました。 [村上さんが報告] 感謝 * 篠田さん * 横山さん * 村上さん * Jun Kuriyamaさん * 畑ヶさん -- HAYASHI Kentaro <hayas****@clear*****>