«前の日記(2010-03-19) 最新 次の日記(2010-03-24)» 編集

ぱぱネット(仮)


2010-03-23 Tokyo Cabinet/Tyrantで遊ぶ(2) [長年日記]

_ [開発][Linux] Tokyo Cabinet/Tyrantで遊ぶ(2)

テーブル型のストレージをサポートし、制限はあるもののRDBMSと似たような感じに使える(はず)の Tokyo Cabinet。 実際にデータを登録して性能を見てみました。

まず生成条件。64bit有効でアライメント力256バイト(2^8)。CabinetではなくTyrantで接続。

dbname="$basedir/chest.tct#opts=l#apow=8#dfunit=2"

1行当たりのデータは....ちょっと仕事のデータを使ってしまったので(ぉ) 具体的には説明できないのですが、整数型x8,文字列型x3です。文字列型(UTF-8)で 1行当たりの平均バイト700バイト程度、最大2.1KBです(*けっこう大きい)。 また、整数カラム5つの完全一致でUNIQUEな制約がついています。SQL風に書くと(仮)、

UNIQUE(emptype, bumonid, groupid, nyuusyanendo, zyugyoincode);

みたいな感じです。上記の条件が全部一致した行は重複して登録したくない、ということです。 このデータを571265行登録してみました。

登録条件は以下の通り。

  1. noidx: インデックスなし, 重複チェックなし
  2. idx: 整数型7種類にDECIMALインデックス,文字列型にQ-GRAMインデックス,重複チェックなし
  3. search: 上記のインデックスを生成しながらUNIQUE制約を1行毎にRDBQRYを発行することで実行

結果は以下の通り。横軸は1万行ごと、縦軸は1秒当たりの処理行数です。

いくらなんでも遅すぎる

1行毎検索遅い!(@_@;)

既存テーブルを検索してみて無かったら新規登録する という処理は非常にありがちだと 思うのですが、ちょっと実用にならないくらい遅い....あまりの遅さに断念しました。

_ [開発][Linux] いやいやKVSなんだからprimary keyを工夫しなくちゃダメでしょ

そうでした。KVSは基本ハッシュデータベースなので、主キーの取り方で制約を実現できるのです。 つまり、ユニークIDをもらってくるこういう関数よりも、

my $id = $jinji->genuid();

どうせ文字列も使えるのだからキーをsprintfか何かで生成してしまえばよいのだと。

my $id = sprintf("%d_%d_%d_%d_%d", $emptype, $bumonid,
          $groupid, $nyuusyanendo, $zyugyoincode);

これなら被ることはないし、被った場合は後から来たデータで上書きされるだけ。 もちろん「登録しない」ということと「上書き」は全く異なる処理だけど、 今回の用途では問題ないのでやってみた。

なんでデータ量に反比例するの

なにデータ量に反比例してんだYO...(´・ω・`)

通常の連想配列の実装では、ハッシュ関数を通すオーバーヘッドはあるはずだが、 キーの長さはほぼ一定なのだから処理時間も一定のはず、なんだけどなー。 これもあまりに遅いので打ち切った。

_ [開発][Linux] 「上書き」がいけないのかな....

後から来たデータで更新するのを抑止するにはputkeep()関数を使えばよいようです (ニューレコードのみ登録する)。 現実には上記のテストデータは全てユニークだから、UNIQUE制約にひっかかることはないので、 put()関数と違いはないと思っていたのですが....

同じじゃん

やっぱり変わりません。 次いこ次。

_ [開発][Linux] 衝突が起きまくっている?

という推測も成り立つ。テーブルデータベースは、 ハッシュテーブルの各要素にBtreeのポインタが入ってる....という実装なのかなあ。 ってことは、ハッシュテーブルが疎になるような設定をしなければならないんだろう。 ざっと基本仕様書読んでbnumは関係ないと勝手に思い込んでいた。 57万件ということは2倍の100万件くらいにしておけばいいかな。

dbname="$basedir/chest.tct#opts=l#bnum=1000000#apow=8#dfunit=2"
同じじゃん!

やっぱり変わりません。 万策尽きてきた.....

_ [開発][Linux] 諦めて基本仕様書を読み直す

基本に立ち戻ってつらつらと.....

bool tctdbsetindex(TCTDB *tdb, const char *name, int type);
`tdb' specifies the table database object connected as a writer.
`name' specifies the name of a column.
      If the name of an existing index is specified,
      the index is rebuilt.
      An empty string means the primary key.

え? An empty string means the primary key. ?? ということはデフォルトでは主キーにもインデックス貼られてないの??? そんなバカな....

$jinji->setindex('', $pm->ITLEXICAL);

を追加。

同じじゃん!

俺にはTokyo Cabinetは使いこなせないようです。

_ [開発][Linux] わかった!!!!!

いままでやってたの全部的外れ!!!!

お気軽全文検索 をやりたかったので安易にQ-GRAMインデックスを張っていたのだが.....仇になった。

Q-GRAMの素片量で劇遅になるわ!

以下のサンプルで再現できる。

  1. Debianでttserverを起動
  2. /tmpにoriginal.txtを置く
  3. perlでtyrant.plを起動

tyrant.plはttserverへ接続してテーブルを登録する。キーは数値。 重複チェックはttserverでおまかせ。1行登録するたびに、 original.txtから1行読んで全文検索のインデックスを貼る、というのが サンプルのアルゴリズム。

しかし、このoriginal.txtが添付の数行みたいなものであれば問題ないのだが.... 多彩な文字の組み合わせを含むソースだとバカみたいに素片量が増えてしまい、 登録時間もうなぎ登りになってしまうようだ。手元では2ちゃんねるのdatログを 数十個結合したもの差し替えてみた。つまりヘッダありAAありというテキスト行が3万行 くらい続いているわけ。これで全文検索のインデックスを作成すると、 毎回確実に適当な単語が追加されていく。

グラフの横軸は1万件ごと、縦軸は1万件を登録するのにかかった秒数。

すごい差だ

ファイルサイズを見てみよう。

-rw-r--r-- 1 root root 125237504 2010-03-23 19:18 testdb.tct
-rw-r--r-- 1 root root    111360 2010-03-23 19:06 testdb.tct.idx.10.dec
-rw-r--r-- 1 root root  23888640 2010-03-23 19:18 testdb.tct.idx.11.dec
-rw-r--r-- 1 root root    111360 2010-03-23 19:06 testdb.tct.idx.2.dec
-rw-r--r-- 1 root root  14170624 2010-03-23 19:18 testdb.tct.idx.3.dec
-rw-r--r-- 1 root root 534364416 2010-03-23 19:18 testdb.tct.idx.6.qgr ※これ!!
-rw-r--r-- 1 root root    111360 2010-03-23 19:06 testdb.tct.idx.7.dec
-rw-r--r-- 1 root root    111360 2010-03-23 19:06 testdb.tct.idx.8.dec
-rw-r--r-- 1 root root    111360 2010-03-23 19:06 testdb.tct.idx.9.dec

これはひどい......... 本文が格納されているであろうtestdb.tctよりはるかにデカイ... 登録時間を一定にするのは難しいんだろうか??できれば単語の種類の量じゃなくて、 毎回登録する1行のテキストの長さだけに処理量が比例して欲しいんだけど.... でも俺が同じもの作ったらさらに1/100くらい遅いだろうしなあウムム.....

まあ、適材適所というか、Q-GRAMは使わないほうがいいですね。


2001|04|
2006|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|03|04|05|06|07|08|09|10|11|12|
2014|01|03|04|05|10|

[BANNER]
このサーバーをもう12年も維持しているかと思うとめまいがしますよ。
ツッコミ機能は、ハンドル名が完全日本語じゃないと登録できません。
また、本文にURLが含まれていても登録できません。
いずれもSPAM対策です。
[Panda Papanda]
2010年
3月
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

[Papanda]  [Kuma]  [Tomorin]  [Iron]  [Eiza]  [Dokkin]  [Honya]  [Zyou]  [Tsuyo]  [Bike]  [KoeBBS]  [Chukei]  [portal]  [tvmatome]  [KaoPaku] 

訪問者数:(11777+2560143)