groongaのデータベースをダンプ・リストアする方法


# はじめに

オープンソースの[カラムストア機能付き全文検索エンジンgroonga](http://groonga.org/ja/)を公開しています。
この記事を書いた時の最新のバージョンは2013年2月28日にリリースした3.0.1です。

今回は、groongaのデータベースをダンプしてバックアップしたり、逆にリストアしてバックアップしたデータを新しいデータベースに再構築する方法を紹介します。（[前々回の記事](http://qiita.com/items/b77f9a256e03801ab66d)でダンプについて少しだけ触れました。）また、新しくリリースされたgroongaに互換性のない変更があったときに、データベースを移行するのにも利用できます。（例えば[groongaの2.1.1には](http://groonga.org/ja/docs/news.html#release-2-1-1-2012-12-29)非互換な変更がありました。）

まず、ダンプするためのサンプルデータを説明します。
そのデータをデータベースに登録した後ダンプし、そのダンプしたデータから新しいデータベースにリストアを実際にコマンドを使って実行していきます。

# ダンプ対象のデータベースの作成

今回は、dump_db/dbという名前のデータベースにデータを追加します。
データを追加した後、このデータベースの中身をダンプします。

最初に次のコマンドを実行します。

```
% groonga -n dump_db/db
```

groongaが入力待機状態になったら、次のテーブルのスキーマを入力します。

```
table_create Books TABLE_HASH_KEY UInt32
column_create Books title COLUMN_SCALAR ShortText
```

Booksというテーブルを作成し、本のタイトルを格納するtitleカラムを作成しました。
このテーブルにloadコマンドでデータを登録します。

```
load --table Books
[
{"_key":1, "title":"Head First Groonga"},
{"_key":2, "title":"Groonga command manual"},
{"_key":3, "title":"Mroonga manual"}
]
```

Booksテーブルにデータが正しく登録できたかを、次のselectコマンドで確認します。

```
select Books --output_columns _key,title
```

上記コマンドの ```--output_columns _key,title``` というのは表示するカラムを指定する引数です。
上のコマンドを実行した結果を見やすいように抜粋し、整形すると以下のようになります。
（なお、以降の実行結果も適宜抜粋・整形しており、実際の実行結果は他にも情報を含んでいます。詳しくは[出力内容についてのドキュメント](http://groonga.org/ja/docs/reference/command/output_format.html)をご覧ください。）

```
[
  [
    [3],
    [["_key","UInt32"],["title","ShortText"]],
    [1,"Head First Groonga"],
    [2,"Groonga command manual"],
    [3,"Mroonga manual"]
  ]
]
```

実行結果を見ると、loadコマンドで登録したデータがあることがわかります。

# ダンプの方法

では、このデータベースの内容をダンプしてみましょう。データベースのダンプにはgroongaの[dump](http://groonga.org/ja/docs/reference/commands/dump.html)コマンドを使います。
次のように実行してみましょう。

```
dump
```

すると次のような実行結果を表示します。

```
table_create Books TABLE_HASH_KEY UInt32
column_create Books title COLUMN_SCALAR ShortText
load --table Books
[
["_key","title"],
[1,"Head First Groonga"],
[2,"Groonga command manual"],
[3,"Mroonga manual"]
]
```

dumpコマンドの実行結果はgroongaのコマンドです。これがgroongaのデータベースをダンプした結果になります。ダンプした結果については後で解説します。まずは、先ほど実行したdumpコマンドから解説します。
dumpコマンドは省略可能な引数としてテーブル名をとることができます。テーブル名を指定した場合はそのテーブルに関するコマンドだけをダンプします。逆に、テーブル名を省略するとデータベース内の全てのテーブルをダンプします。今回は1つしかテーブルを作成していないので省略しました。もし```Books``` テーブルを指定してダンプする時は ```dump Books``` と実行します。

次に、dumpコマンドが表示した内容を見てみましょう。ここまでに実行したgroongaコマンドとほぼ同じものになっているのがわかります。1つだけ違う点は、loadコマンドで指定しているデータの形式だけが異なっています。形式が違うだけで、登録するデータは同じです。

loadコマンドが登録するデータが本当に同じか確かめるために、ダンプしたgroongaのコマンドからデータベースをリストアしましょう。その前に、まずは上記のダンプしたコマンドをファイルに書き込みます。ファイルに書き込むと、コマンド一発でリストアできて便利だからです。ファイルに書き込むには、一度groongaを終了してから、次のコマンドを端末上で実行します。

```
% groonga dump_db/db dump > dump.grn
```

このコマンドで、dump_db/dbデータベースを使ってgroongaにdumpコマンドを実行させ、その結果をdump.grnというファイルに書き込んでいます。
標準入力からgroongaのコマンドを指定すると、groongaはその実行結果を標準出力に出力します。その出力をリダイレクトを使ってdump.grnというファイルに書き込んでいます。
そのため、次のコマンドを端末上で実行してdump.grnの中身を確認すると、先ほどのdumpコマンドの実行結果と同じ内容になっています。

```
% cat dump.grn
```

# リストアの方法

ダンプしたコマンドをファイルに書き込んだところで、ダンプしたコマンドからデータベースをリストアしてみましょう。
ここではデータベースrestore_db/dbに対してリストアしてみます。端末上で次のコマンドを実行してください。

```
% groonga -n restore_db/db < dump.grn
```

これは、新しくrestore_db/dbというデータベースを作成し、そのデータベースに対してdump.grnに書かれたコマンドを実行し終了するという意味です。
先ほどコマンドラインでdumpコマンドを実行した時と同じように、標準入力からgroongaのコマンドを指定しています。

さて、ちゃんとリストアできているか確認しましょう。まずは次のようにgroongaを実行し、restore_db/dbを開きます。

```
% groonga restore_db/db
```

次に、最初にdump_db/dbに対して実行したselectコマンドを実行してみます。

```
select Books --output_columns _key,title
```

実行結果は次のようになります。

```
[
  [
    [3],
    [["_key","UInt32"],["title","ShortText"]],
    [1,"Head First Groonga"],
    [2,"Groonga command manual"],
    [3,"Mroonga manual"]
  ]
]
```

実行結果と、dump_db/dbに対してselectコマンドを実行した時の結果を比べてみると、同じデータになっているのがわかります。よって、最初に作成したデータベースが新しいデータベースにリストアできているのが確認できました。

# 補足：rroongaを使っている方向けのダンプ・リストアの方法

groongaのRubyバインディングである[rroonga](http://ranguba.org/ja/#about-rroonga)をインストールされている方は、grndumpコマンドを使ってデータベースをダンプすることができます。もしインストールされていない方でも、次のコマンドを実行するとインストールできます。

```
% gem install rroonga
```

さて、先ほどdump_db/dbをダンプした時のコマンドは次のようなものでした。

```
% groonga dump_db/db dump > dump.grn
```

同じ事をgrndumpコマンドを使って行うと次のようになります。

```
% grndump dump_db/db > dump.grn
```

これだけだと、groongaコマンドを実行する場合と大した違いはありませんが、grndumpには他にもオプションを指定することができます。テーブルのスキーマを定義するコマンドだけをダンプしたり、逆にデータを登録するコマンドだけをダンプすることもできます。例えば、dump_db/dbデータベースからスキーマを定義するコマンドだけを取出するときは次のように実行します。

```
% grndump --no-dump-tables dump_db/db
```

このコマンドを実行すると、次のような表示が出ます。

```
table_create Books TABLE_HASH_KEY --key_type UInt32
column_create Books title COLUMN_SCALAR ShortText
```

table_createコマンドなどのスキーマを定義するコマンドだけを、grndumpコマンドがダンプしたのがわかります。今回の場合なら、Booksテーブルのスキーマはそのままで別の本を新しいデータベースには登録したい、というときに便利です。
他にも、grndumpにはダンプするテーブルの絞り込みなどのオプションがあります。オプションの種類と使い方は ```grndump --help``` を実行してみてください。

また、rroongaを使ってデータベースのリストアもできます。先ほどgroongaコマンドでリストアしたのと同じ動作を書いてみます。なお、groongaコマンドでリストアした時は次のように実行しました。

```
% groonga -n restore_db/db < dump.grn
```

次の例のようなRubyのコードを書くと、このコマンドと同じようにrestore_db/dbに対してdump.grnの内容でリストアできます。

```ruby
require "groonga"

Groonga::Database.create(:path => "restore_db/db")
context = Groonga::Context.default
File.open("dump.grn") do |dump_file|
  context.restore(dump_file)
end
```

上記の例で使っているrestoreメソッドは、渡されたオブジェクトから1行ずつコマンドを読み込んでリストアします。resotreメソッドはFileオブジェクトやStringオブジェクトなど、each_lineメソッドをもつオブジェクトを引数として受け取ることができます。上記の例ではFileオブジェクトを渡していますが、文字列を渡す場合は次のように書きます。（この記事を投稿した時点では次のコードを紹介していました。）

```ruby
require "groonga"

Groonga::Database.create(:path => "restore_db/db")
dumped_commands = File.read("dump.grn")
context = Groonga::Context.default
context.restore(dumped_commands)
```

ダンプしたコマンドが少ない場合はどちらの例でも問題ありません。もし、ダンプしたコマンドが多い場合は最初の例のようにFileオブジェクトをresotreメソッドに渡してください。2つ目の例（Stringオブジェクトを渡す場合）は最初にダンプしたコマンドをファイルからすべてメモリ上に読み込んでから1行ずつリストアしているので、ダンプしたコマンドが多い場合だとメモリを多く使ってしまうためです。1つ目の例のようにFileオブジェクトを渡すと、1行ずつメモリ上に読み込んでリストアするためメモリの消費を少なくします。

# まとめ

今回はgroongaでバックアップするときに必要となる、ダンプとリストアの方法について紹介しました。
もしものときのために、データベースのバックアップを取っておくと安心です。それ以外にも、データを移行したいときに利用できます。

groongaに興味を持ったなら、まずは[インストール](http://groonga.org/ja/docs/install.html)して試してみてください。

groongaの基本的な動作を知るための[チュートリアル](http://groonga.org/ja/docs/tutorial.html)もあります。インストールしたら試してみてください。

また、今回はrroongaについても紹介しました。rroongaを使うとRubyから簡単にgroongaを使うことができます。rroongaについて詳しくは[rroongaのドキュメント](http://ranguba.org/rroonga/ja/)をご覧ください。（[チュートリアル](http://ranguba.org/rroonga/ja/file.tutorial.html)もあります。）