[Perl] Tokyo Cabinetのインストール手順~テーブルデータベースを試す

Tokyo Cabinet は、
 ・memcached 互換のオンメモリのキャッシュサーバ
 ・データがディスクに保存される高速な key-value ストア
といった特長がありますが、それに加えて後者を拡張した
 ・リレーショナル DB のようにカラムごとに検索条件を付けたクエリで検索できる DBMS
の機能があって、興味深いです。

テーブルデータベースは、リレーショナルデータベースのテーブルのように、複数の列からなるレコードを格納できるデータベースです。ハッシュデータベースのように主キーでレコードを識別しながらも、リレーショナルデータベースのようにレコード内に名前をつけた複数のコラムを持たせることができます。ハッシュデータベースと違って、レコード内の個々のコラムの値を条件にしてレコードの集合を問い合わせることができます。リレーショナルデータベースとは違って、あらかじめスキーマを定義する必要がなく、レコード毎に異なる種類のコラムを持たせることができます。
http://tokyocabinet.sourceforge.net/spex-ja.html#tips_tctdb

スキーマがないので、カラムを追加する度にスキーマ変更する必要もなく、自由度が高い。
『データは JSON みたいにまるっと入れておきたいけど、インデックスを張って検索もしたい』といった場合に便利そうなので、試してみました。

1. 準備


手元の環境では bzlib.h が無かったので、予め入れておきます。

sudo apt-get install libbz2-dev

手元の環境(Debian)では、必要なのはこれだけでした。

2. インストール


Tokyo Cabinet(ストレージ)、Tokyo Tyrant(サーバ)と、
Tokyo Tyrant の Perl クライアントである TokyoTyrant.pm のソースを
ダウンロード、コンパイルして、インストールしていきます。
今回は、/usr/local/tokyo***-1.x.xx というディレクトリに入れています。
テスト後に不要になったら、ディレクトリごと削除すれば済むので安心。

wget http://tokyocabinet.sourceforge.net/tokyocabinet-1.4.17.tar.gz
wget http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-1.1.23.tar.gz
wget http://tokyocabinet.sourceforge.net/tyrantperlpkg/tokyotyrant-perl-1.10.tar.gz

tar zxvf tokyocabinet-1.4.17.tar.gz
tar zxvf tokyotyrant-1.1.23.tar.gz
tar zxvf tokyotyrant-perl-1.10.tar.gz

cd tokyocabinet-1.4.17
./configure --prefix=/usr/local/tokyocabinet-1.4.17 && make
sudo make install
cd ..

cd tokyotyrant-1.1.23
./configure --prefix=/usr/local/tokyotyrant-1.1.23 --with-tc=/usr/local/tokyocabinet-1.4.17 && make
sudo make install
cd ..

cd tokyotyrant-perl-1.10
perl Makefile.PL && make
sudo make install
cd ..

なお、TokyoTyrant.pm は↓あたりに入ります。
/usr/local/share/perl/5.10.0/TokyoTyrant.pm

3. Tokyo Tyrant のサーバ起動


Apache における apachectl のようなサーバ起動の管理コマンド ttservctl が
用意されているので、それを使ってサーバを起動します。パスを通して実行。

sudo env \
    LD_LIBRARY_PATH=/usr/local/tokyocabinet-1.4.17/lib \
    PATH=/usr/local/tokyotyrant-1.1.23/bin:$PATH \
    /usr/local/tokyotyrant-1.1.23/sbin/ttservctl start

なお、サーバの終了手順は以下の通り。

sudo /usr/local/tokyotyrant-1.1.23/sbin/ttservctl stop

4. Tokyo Tyrant に接続してみる


接続テストには tcrmgr コマンドが利用できます。まずパスを通します。

export LD_LIBRARY_PATH=/usr/local/tokyocabinet-1.4.17/lib
export PATH=/usr/local/tokyotyrant-1.1.23/bin:$PATH

値を書き込むには、put、ホスト名、key、value という引数を指定します。

tcrmgr put localhost foo bar

値を読み出すには、get、ホスト名、key という引数を指定します。

tcrmgr get localhost foo

『bar』と表示されれば成功です。
サーバ経由で値の読み書きができました。

5. Perl クライアントで接続してみる


TokyoTyrant.pm を使って接続してみます。

#!/usr/bin/perl

use strict;
use TokyoTyrant;

my $rdb = TokyoTyrant::RDB->new();
$rdb->open("localhost", 1978) or die "open error: ".$rdb->errmsg($rdb->ecode);
$rdb->put("foo","bar") or die "put error: ".$rdb->errmsg($rdb->ecode);
my $value = $rdb->get("foo");
defined $value or die "get error: ".$rdb->errmsg($rdb->ecode);
printf("%s\n", $value);
$rdb->close() or die "close error: ".$rdb->errmsg($rdb->ecode);

『bar』と表示されれば成功です。
詳しいドキュメントは、perldoc TokyoTyrant で表示されます。

6. 「テーブルデータベース」の利用


Tokyo Cabinet には複数のデータ形式があり、ストレージとなる ファイル名の拡張子 で形式が判別されます。

  ・".tch" ハッシュデータベース
  ・".tcb" B+木データベース
  ・".tct" テーブルデータベース

テーブルデータベースを利用するためには、ttservctl を編集する必要があります。
いったん、ttservctl stop してから書き換えます。
sudo vi /usr/local/tokyotyrant-1.1.23/sbin/ttservctl
書き換える箇所は、dbname の行です。
basedir="/var/ttserver"
port="1978"
dbname="$basedir/casket.tch#bnum=1000000"
デフォルトでは /var/ttserver/casket.tch のハッシュデータベースを利用しています。
dbname="$basedir/casket.tct#bnum=1000000"
/var/ttserver/casket.tct のテーブルデータベースに変更しました。
再び、ttservctl start すればテーブルデータベースが利用可能になります。
ポート番号の設定は変えていないので、デフォルトの 1978 ポートのままです。

6. Perl からテーブルデータベースの利用


それでは、TokyoTyrant.pm からテーブルデータベースにアクセスしてみます。

#!/usr/bin/perl

use strict;
use TokyoTyrant;

my $rdb = TokyoTyrant::RDBTBL->new();
$rdb->open("localhost", 1978) or die "open error: ".$rdb->errmsg($rdb->ecode);

print $rdb->stat();

my $pkey = $rdb->genuid();
die "genuid error: ".$rdb->errmsg($rdb->ecode) if ( $pkey == -1 );
print "genuid: ", $pkey, "\n";

my $cols = { "name" => "kawanet", "age" => "32", "lang" => "ja,en,perl" };
$rdb->put($pkey,$cols) or die "put error: ".$rdb->errmsg($rdb->ecode);

my $qry = TokyoTyrant::RDBQRY->new($rdb);
$qry->addcond("age", $qry->QCNUMEQ, "32");
$qry->setorder("name", $qry->QOSTRASC);
$qry->setlimit(10);

my $num = $qry->searchcount();
print "count: ", $num, "\n";

my $res = $qry->search();
my $cnt = 0;
foreach my $rkey (@$res){
    print "[",++$cnt,"]\n";
    my $rcols = $rdb->get($rkey);
    foreach my $key ( sort keys %$rcols ) {
        print $key, "\t", $rcols->{$key}, "\n";
    }
}

$rdb->close() or die "close error: ".$rdb->errmsg($rdb->ecode);

実行結果は以下の通り。
type が table(テーブルデータベース)になっており、
QCNUMEQ で指定した条件のレコードが抽出できました。

perl db.pl
version 1.1.23
libver  306
protver 0.91
os      Linux
time    1241088729.147036
pid     24130
sid     1545951491
type    table
rnum    0
size    4198720
bigend  0
fd      6
loadavg 0.040000
ru_real 54.346143
ru_user 0.000000
ru_sys  0.116007
genuid: 1
count: 1
[1]
age     32
lang    ja,en,perl
name    kawanet

以上、今回はとりあえずインストールとテストまで。
実際にデータを入れてベンチマークも取ってみたい。

(参考)利用できる検索条件


テーブルデータベースで利用できる 検索条件 は、以下の通り。
  • TDBQCSTREQ : 文字列 完全一致
  • TDBQCSTRINC : 文字列 部分一致
  • TDBQCSTRBW : 文字列 前方一致
  • TDBQCSTREW : 文字列 後方一致
  • TDBQCSTRAND : カンマ区切りの文字列の全てを含む
  • TDBQCSTROR : カンマ区切りの文字列のいずれかを含む
  • TDBQCSTROREQ : カンマ区切りの文字列のいずれかと完全一致する
  • TDBQCSTRRX : 文字列 正規表現で一致
  • TDBQCNUMEQ : 数値比較 eq(=)
  • TDBQCNUMGT : 数値比較 gt(>)
  • TDBQCNUMGE : 数値比較 ge(≧)
  • TDBQCNUMLT : 数値比較 lt(<)
  • TDBQCNUMLE : 数値比較 le(≦)
  • TDBQCNUMBT : 数値比較 between(カンマ区切り)
  • TDBQCNUMOREQ : 数値比較 in (A,B,C,...) いずれかと一致

SQL::Statement あたりと組み合わせて DBD::TokyoTyrant とか作れば、
DBI 経由に SQL 文で検索するようにもできるかな?(初めから RDBMS を使え)

ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 12

なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー)
驚いた
面白い 面白い
ナイス ナイス ナイス ナイス
ガッツ(がんばれ!)
かわいい かわいい

この記事へのコメント

otacon
2010年03月19日 00:19
6. Perl からテーブルデータベースの利用
ここのスクリプトなんですが下の2つの行は入替しないとダメじゃないですか?
----------------------------
$qry->setlimit(10);

$num = $qry->searchcount();

----------------------------
setlimitメソッドを10にしたら
searchcount()で該当するものが本当は100件あったとしても
10件って出ませんか?

この記事へのトラックバック