Groonga 4.0.7の実験的機能であるカラム値の圧縮とRroongaからそれを使うには - 2014-11-18 - ククログ

ククログ

株式会社クリアコード > ククログ > Groonga 4.0.7の実験的機能であるカラム値の圧縮とRroongaからそれを使うには

Groonga 4.0.7の実験的機能であるカラム値の圧縮とRroongaからそれを使うには

はじめに

オープンソースのカラムストア機能付き全文検索エンジンとしてGroongaがあります。 この記事を書いている時点の最新版であるGroonga 4.0.7では、カラムの値を圧縮して保存することができるようになりました。

今回は、そのカラム圧縮がどれほど有効なのか、また、Groongaの機能をRubyから利用するためのライブラリであるRroongaから使うやりかたを紹介します。

カラム圧縮機能が嬉しいケースとは

Groonga 4.0.7ではzlibもしくは、lz4による圧縮を実験的にサポートしています。 どんなケースだと嬉しいのでしょうか。

  • カラムのデータがそれなりに大きい

数バイトや数10バイト程度では、圧縮する方がサイズが大きくなる可能性があります。また、圧縮・展開のオーバーヘッドを無視できない可能性があります。 しかし、カラムに格納しているデータがそれなりに大きいのであればディスク容量を節約できます。

  • 主な用途が全文検索のみである

圧縮したカラムでもソートやドリルダウンできますが、データコピーが発生するので非圧縮の場合よりも遅くなります。 そのため、Wikipediaの本文データなど、ソートやドリルダウンの対象としないようなデータを格納しているカラムを圧縮するのが効果的です。

Groongaでカラム圧縮機能を試してみる

では、実際に試してみましょう。 サンプルデータとしては、Wikipediaのデータを使ってみます。

ストリーム指向の処理モデルを採用した分散全文検索エンジンであるDroongaのベンチマーク手順を利用するとデータの準備が簡単なので今回はそれを使います。

wikipedia-searchはDroongaを使ってWikipediaを検索するためのサンプルアプリケーションです。

サンプルデータを用意する

あらかじめ、Groongaをインストールしてあるものとします。

次に、wikipedia-search ベンチマーク取得手順にあるようにwikipedia-searchのリポジトリデータを取得して、データの準備をしておきます。

% git clone https://github.com/droonga/wikipedia-search.git
% cd wikipedia-search
% bundle install
% MAX_N_RECORDS=1000000 rake data:convert:groonga:ja

rake data:convert:groonga:jaを実行すると、Wikipediaの最新のアーカイブデータ(jawiki-latest-pages-articles.xml.bz2)をダウンロードしはじめます。1.88GiBあるのでダウンロードが完了するまでしばらく待ちます。 ダウンロード後にGroongaにデータを投入するためのデータファイル(data/groonga/ja-pages.grn)が生成されます。

デフォルトだと5000件の.grnファイルを生成しますが、データ件数をMAX_N_RECORDSで指定して、100万件のデータを生成します。

非圧縮のGroongaのデータベースを構築する

次のようにして、従来のカラム圧縮を利用しない非圧縮のデータベースを構築します。 スキーマ定義は、config/groonga以下にschema.grnがあります。インデックスの定義も同様にindexes.grnがあるのでそれを使います。

% groonga -n testdb-normal/db quit
% cat config/groonga/schema.grn | groonga testdb-normal/db
% cat config/groonga/indexes.grn | groonga testdb-normal/db
% cat data/groonga/ja-pages.grn | groonga testdb-normal/db

カラム圧縮(zlib)のGroongaのデータベースを構築する

今度はカラム圧縮(zlib)のデータベースを構築します。 カラム圧縮(zlib)を適用するには、schema.grnを一行修正します。

column_create Pages text COLUMN_SCALAR|COMPRESS_ZLIB Text

あとは、非圧縮の場合と同じようにしてデータベースを構築します。

% groonga -n testdb-zlib/db quit
% cat config/groonga/schema-zlib.grn | groonga testdb-zlib/db
% cat config/groonga/indexes.grn | groonga testdb-zlib/db
% cat data/groonga/ja-pages.grn | groonga testdb-zlib/db

カラム圧縮(lz4)のGroongaのデータベースを構築する

今度はカラム圧縮(lz4)のデータベースを構築します。 カラム圧縮(lz4)を適用するには、schema.grnを一行修正します。

column_create Pages text COLUMN_SCALAR|COMPRESS_LZ4 Text

あとは、非圧縮の場合と同じようにしてデータベースを構築します。

% groonga -n testdb-lz4/db quit
% cat config/groonga/schema-lz4.grn | groonga testdb-lz4/db
% cat config/groonga/indexes.grn | groonga testdb-lz4/db
% cat data/groonga/ja-pages.grn | groonga testdb-lz4/db

データベースのサイズを比較してみる

ここまでで、非圧縮、カラム圧縮(zlib)、カラム圧縮(lz4)それぞれでデータベースを作成しました。それぞれのデータベースが占めるディスク容量(GiB)をグラフにすると以下のようになりました。

画像の説明

カラム圧縮(zlib)が約2.3GiB、カラム圧縮(lz4)が約2.5GiB、非圧縮で約3GiBという結果です。 ここではベンチマークについては割愛しますが、まずはカラム圧縮(lz4)を試してみることをおすすめします。もしもっとディスク容量を節約したいならカラム圧縮(zlib)を使ってみてください。

Rroongaでカラム圧縮機能を試してみる

カラム圧縮の有用性がわかったところで、今度はそれをRroongaでもつかってみることにしましょう。 RroongaでGroonga 4.0.7のカラム圧縮機能を利用するにはRroonga 4.0.6が必要です。 Rroongaはgemとして提供されているので、以下のようにして簡単にインストールすることができます。

% gem install rroonga

Rroongaで検索するだけなら、先ほどのデータベースをそのまま使えます。では、Rroongaを使って同じようなスキーマ定義を実現するにはどのようにすればよいのでしょうか。 Groongaの場合と見比べてみましょう。

schema.grnの内容は次のとおりでした。

table_create Categories TABLE_HASH_KEY ShortText
table_create Pages TABLE_HASH_KEY UInt64
column_create Pages title COLUMN_SCALAR ShortText
column_create Pages text COLUMN_SCALAR|COMPRESS_LZ4 Text
column_create Pages categories COLUMN_VECTOR Categories

これをRroongaでは次のようにして定義します。

require "groonga"

Groonga::Schema.define do |schema|
  schema.create_table("Categories", :type => :hash) do |table|
  end
  schema.create_table("Pages",
                      :type => :hash,
                      :key_type => "UInt64") do |table|
    table.short_text("title")
    table.text("text", :compress => :lz4)
    table.reference("categories", "Categories", :type => :vector)
  end
end

注目するポイントは次の箇所です。

table.text("text", :compress => :lz4)
  • table.textはtext型のカラムを定義することを意味します。
  • "text"はカラム名が"text"であることを意味します。
  • :compressで圧縮方法を指定します。この場合はLZ4を使うことを意味します。zlibなら:zlibを指定します。デフォルトは非圧縮です。

カラム圧縮を利用するのとは直接関係ないのですが、インデックスについてはどうでしょうか。 indexes.grnの内容は次のとおりでした。

column_create Categories pages_categories COLUMN_INDEX Pages categories

table_create Terms TABLE_PAT_KEY ShortText \
  --default_tokenizer TokenBigram \
  --normalizer NormalizerAuto
column_create Terms pages COLUMN_INDEX|WITH_SECTION|WITH_POSITION \
  Pages title,text

これをRroongaでは次のようにして定義します。

require "groonga"
Groonga::Schema.define do |schema|
  schema.change_table("Categories") do |table|
    table.index("Pages.categories")
  end

  schema.create_table("Terms",
                      :type => :patricia_trie,
                      :default_tokenizer => :bigram,
                      :normalizer => "NormalizerAuto") do |table|
    table.index("Pages", "title", "text",
                :with_section => true,
                :with_position => true)
  end
end

Rubyらしい書き方で定義できることがわかりますね。

まとめ

今回は、Groonga 4.0.7から導入されたカラム圧縮機能とGroongaをRubyから利用するライブラリであるRroongaでのスキーマ定義について紹介しました。

来週末の11月29日(いい肉の日)には、全文検索エンジンGroongaを囲む夕べ5というGroongaとその関連プロダクトに関するイベントがあります。 Groongaと関連プロダクトやツールの最新動向を知るのにおススメです。

また、このイベントの休憩時間には検索エンジン自作入門の著者である山田さん、末永さんによるサイン会も開催します。 ぜひ、来週末の全文検索エンジンGroongaを囲む夕べ5に参加してみませんか?