2013年8月20日火曜日

mroongaのインデックスサイズをなんとなく

ウチではかつてはTritonn全盛、今はmroonga全盛な「MySQL de FullTextSearch」が大好きな感じでやっています。Sphinxとか誰か手を出さないかなぁと思いつつ、いい加減MySQL de FTSから足を洗って全文検索ライブラリはMySQLとは連携させないでやろうぜ、というのもあったりします。

そこで取り敢えず現状の洗い出し(?)の一環として、mroongaのストレージサイズをぼんやりと考えてみることにします。
というか運用している分にはこれがキツい。
インデックス用のmrnファイルは(tokenBigramなせいもあって)データサイズに対して線形に増えるので、ストレージ容量と、あとそれをキャッシュするだけのメモリ増設がもうままならない。


実際どれくらい食うのかを取り敢えず測ってみる。

サンプルデータはTwitterのツイート履歴。
ただし全文検索が試したいだけだったり、カラムをもろもろ列挙したりするのがものすごく面倒だったのでテーブル構成はすごく手抜きな感じで。

mysql55> CREATE TABLE myisam.tweet ( tweet_id BIGINT UNSIGNED PRIMARY KEY, timestamp TIMESTAMP NOT NULL DEFAULT 0, text TEXT) Engine = MyISAM;
Query OK, 0 rows affected (0.03 sec)

mysql55> CREATE TABLE mroonga_storage.tweet ( tweet_id BIGINT UNSIGNED PRIMARY KEY, timestamp TIMESTAMP NOT NULL DEFAULT 0, text TEXT) Engine = mroonga;
Query OK, 0 rows affected (0.07 sec)

mysql55> CREATE TABLE mroonga_wrapper.tweet ( tweet_id BIGINT UNSIGNED PRIMARY KEY, timestamp TIMESTAMP NOT NULL DEFAULT 0, text TEXT) Engine = mroonga COMMENT = 'Engine "MyISAM"';
Query OK, 0 rows affected (0.09 sec)

MyISAM、ストレージモード、ラッパーモードでそれぞれ作る。
mroongaはデータベース単位でmrnファイルを作ってしまうのでデータベースも分けておく。

mysql55> SHOW TABLE STATUS FROM myisam\G
*************************** 1. row ***************************
           Name: tweet
         Engine: MyISAM
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 0
Max_data_length: 281474976710655
   Index_length: 1024
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2013-08-19 19:39:02
    Update_time: 2013-08-19 19:39:02
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.01 sec)

mysql55> SHOW TABLE STATUS FROM mroonga_storage\G
*************************** 1. row ***************************
           Name: tweet
         Engine: mroonga
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 4526080
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: NULL
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.01 sec)

mysql55> SHOW TABLE STATUS FROM mroonga_wrapper\G
*************************** 1. row ***************************
           Name: tweet
         Engine: mroonga
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 0
Max_data_length: 0
   Index_length: 1024
      Data_free: 0
 Auto_increment: NULL
    Create_time: NULL
    Update_time: 2013-08-19 19:39:09
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment: Engine "MyISAM"
1 row in set (0.01 sec)

$ ls -l myisam/* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql   61  8月 19 19:38 2013 myisam/db.opt
-rw-rw---- 1 mysql mysql    0  8月 19 19:39 2013 myisam/tweet.MYD
-rw-rw---- 1 mysql mysql 1024  8月 19 19:39 2013 myisam/tweet.MYI
-rw-rw---- 1 mysql mysql 8638  8月 19 19:39 2013 myisam/tweet.frm
9723

$ ls -l mroonga_storage* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql     4096  8月 19 19:39 2013 mroonga_storage.mrn
-rw-rw---- 1 mysql mysql 12857344  8月 19 19:39 2013 mroonga_storage.mrn.0000000
-rw-rw---- 1 mysql mysql  4243456  8月 19 19:39 2013 mroonga_storage.mrn.0000103
-rw-rw---- 1 mysql mysql     4096  8月 19 19:39 2013 mroonga_storage.mrn.0000104
-rw-rw---- 1 mysql mysql     4096  8月 19 19:39 2013 mroonga_storage.mrn.0000105
-rw-rw---- 1 mysql mysql   274432  8月 19 19:39 2013 mroonga_storage.mrn.0000106
-rw-rw---- 1 mysql mysql  1048576  8月 19 19:39 2013 mroonga_storage.mrn.001

mroonga_storage:
合計 16
-rw-rw---- 1 mysql mysql   61  8月 19 19:38 2013 db.opt
-rw-rw---- 1 mysql mysql 8638  8月 19 19:39 2013 tweet.frm
18444795

$ ls -l mroonga_wrapper* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql     4096  8月 19 19:39 2013 mroonga_wrapper.mrn
-rw-rw---- 1 mysql mysql 12857344  8月 19 19:39 2013 mroonga_wrapper.mrn.0000000
-rw-rw---- 1 mysql mysql    65536  8月 19 19:39 2013 mroonga_wrapper.mrn.0000103
-rw-rw---- 1 mysql mysql  1048576  8月 19 19:39 2013 mroonga_wrapper.mrn.001

mroonga_wrapper:
合計 20
-rw-rw---- 1 mysql mysql   61  8月 19 19:38 2013 db.opt
-rw-rw---- 1 mysql mysql    0  8月 19 19:39 2013 tweet.MYD
-rw-rw---- 1 mysql mysql 1024  8月 19 19:39 2013 tweet.MYI
-rw-rw---- 1 mysql mysql 8638  8月 19 19:39 2013 tweet.frm
13985275
mroonga_storage, mroonga_wrapperの差とmroonga_storageのSHOW TABLE STATUSの結果から察するに、.mrn.0000103が.MYDファイルみたいな扱いになるんだろうか。

LOAD DATA INFILEで1万ツイートほど流し込んでみる。

mysql55> LOAD DATA INFILE '/tmp/tweets.csv' INTO TABLE tweet FIELDS TERMINATED BY ',' ENCLOSED BY  '"' IGNORE 1 LINES (tweet_id, @dummy, @dummy, @dummy, @dummy, timestamp, @dummy, text, @dummy);
Query OK, 10045 rows affected, 10089 warnings (0.25 sec)
Records: 10045  Deleted: 0  Skipped: 0  Warnings: 10089
timestampカラムのデータを切り詰めたとかフィールドの数が合わないってワーニングが出てたけど大勢に影響がないので気にしない。

mysql55> SHOW TABLE STATUS FROM myisam\G
*************************** 1. row ***************************
           Name: tweet
         Engine: MyISAM
        Version: 10
     Row_format: Dynamic
           Rows: 10045
 Avg_row_length: 125
    Data_length: 1263404
Max_data_length: 281474976710655
   Index_length: 217088
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2013-08-19 19:39:02
    Update_time: 2013-08-19 19:41:06
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

mysql55> SHOW TABLE STATUS FROM mroonga_storage\G
*************************** 1. row ***************************
           Name: tweet
         Engine: mroonga
        Version: 10
     Row_format: Dynamic
           Rows: 10045
 Avg_row_length: 0
    Data_length: 46469120
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: NULL
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

mysql55> SHOW TABLE STATUS FROM mroonga_wrapper\G
*************************** 1. row ***************************
           Name: tweet
         Engine: mroonga
        Version: 10
     Row_format: Dynamic
           Rows: 10045
 Avg_row_length: 125
    Data_length: 1263404
Max_data_length: 0
   Index_length: 217088
      Data_free: 0
 Auto_increment: NULL
    Create_time: NULL
    Update_time: 2013-08-19 19:41:19
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment: Engine "MyISAM"
1 row in set (0.00 sec)

$ ls -l myisam/* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql      61  8月 19 19:38 2013 myisam/db.opt
-rw-rw---- 1 mysql mysql 1263404  8月 19 19:41 2013 myisam/tweet.MYD
-rw-rw---- 1 mysql mysql  217088  8月 19 19:41 2013 myisam/tweet.MYI
-rw-rw---- 1 mysql mysql    8638  8月 19 19:39 2013 myisam/tweet.frm
1489191

$ ls -l mroonga_storage* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql     4096  8月 19 19:41 2013 mroonga_storage.mrn
-rw-rw---- 1 mysql mysql 12857344  8月 19 19:39 2013 mroonga_storage.mrn.0000000
-rw-rw---- 1 mysql mysql  8437760  8月 19 19:41 2013 mroonga_storage.mrn.0000103
-rw-rw---- 1 mysql mysql  4198400  8月 19 19:41 2013 mroonga_storage.mrn.0000104
-rw-rw---- 1 mysql mysql  4198400  8月 19 19:41 2013 mroonga_storage.mrn.0000105
-rw-rw---- 1 mysql mysql 29634560  8月 19 19:41 2013 mroonga_storage.mrn.0000106
-rw-rw---- 1 mysql mysql  1048576  8月 19 19:39 2013 mroonga_storage.mrn.001

mroonga_storage:
合計 16
-rw-rw---- 1 mysql mysql   61  8月 19 19:38 2013 db.opt
-rw-rw---- 1 mysql mysql 8638  8月 19 19:39 2013 tweet.frm
60387835

$ ls -l mroonga_wrapper* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql     4096  8月 19 19:39 2013 mroonga_wrapper.mrn
-rw-rw---- 1 mysql mysql 12857344  8月 19 19:39 2013 mroonga_wrapper.mrn.0000000
-rw-rw---- 1 mysql mysql    65536  8月 19 19:39 2013 mroonga_wrapper.mrn.0000103
-rw-rw---- 1 mysql mysql  1048576  8月 19 19:39 2013 mroonga_wrapper.mrn.001

mroonga_wrapper:
合計 1464
-rw-rw---- 1 mysql mysql      61  8月 19 19:38 2013 db.opt
-rw-rw---- 1 mysql mysql 1263404  8月 19 19:41 2013 tweet.MYD
-rw-rw---- 1 mysql mysql  217088  8月 19 19:41 2013 tweet.MYI
-rw-rw---- 1 mysql mysql    8638  8月 19 19:39 2013 tweet.frm
15464743

更新時刻やファイルサイズからして、.mrnと.mrn.000000はなんかテーブル情報持ってて、.mrn.00010x(から連番になるんだろう)ファイルがデータ本体ぽい。足すとData_lengthっぽくなるし。
MyISAMのテーブルはフルテキストインデックス作る気がないのでここまでとして、mroonga_storageとmroonga_wrapperでそれぞれインデックスを作ってみる。

mysql55> ALTER TABLE mroonga_storage.tweet ADD FULLTEXT KEY (text) COMMENT 'parser "TokenBigram"';
Query OK, 0 rows affected (0.48 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql55> ALTER TABLE mroonga_wrapper.tweet ADD FULLTEXT KEY (text) COMMENT 'parser "TokenBigram"';
Query OK, 10045 rows affected (1.18 sec)
Records: 10045  Duplicates: 0  Warnings: 0

mysql55> SHOW TABLE STATUS FROM mroonga_storage\G
*************************** 1. row ***************************
           Name: tweet
         Engine: mroonga
        Version: 10
     Row_format: Dynamic
           Rows: 10045
 Avg_row_length: 0
    Data_length: 46469120
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: NULL
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

mysql55> SHOW TABLE STATUS FROM mroonga_wrapper\G
*************************** 1. row ***************************
           Name: tweet
         Engine: mroonga
        Version: 10
     Row_format: Dynamic
           Rows: 10045
 Avg_row_length: 125
    Data_length: 1263404
Max_data_length: 0
   Index_length: 217088
      Data_free: 0
 Auto_increment: NULL
    Create_time: NULL
    Update_time: 2013-08-19 19:45:54
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment: Engine "MyISAM"
1 row in set (0.00 sec)

$ ls -l mroonga_storage* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql     4096  8月 19 19:45 2013 mroonga_storage.mrn
-rw-rw---- 1 mysql mysql 17051648  8月 19 19:45 2013 mroonga_storage.mrn.0000000
-rw-rw---- 1 mysql mysql  8437760  8月 19 19:41 2013 mroonga_storage.mrn.0000103
-rw-rw---- 1 mysql mysql  4198400  8月 19 19:41 2013 mroonga_storage.mrn.0000104
-rw-rw---- 1 mysql mysql  4198400  8月 19 19:41 2013 mroonga_storage.mrn.0000105
-rw-rw---- 1 mysql mysql 29634560  8月 19 19:41 2013 mroonga_storage.mrn.0000106
-rw-rw---- 1 mysql mysql  8437760  8月 19 19:45 2013 mroonga_storage.mrn.0000107
-rw-rw---- 1 mysql mysql  2134016  8月 19 19:45 2013 mroonga_storage.mrn.0000108
-rw-rw---- 1 mysql mysql  8392704  8月 19 19:45 2013 mroonga_storage.mrn.0000108.c
-rw-rw---- 1 mysql mysql  1048576  8月 19 19:45 2013 mroonga_storage.mrn.001

mroonga_storage:
合計 16
-rw-rw---- 1 mysql mysql   61  8月 19 19:38 2013 db.opt
-rw-rw---- 1 mysql mysql 8638  8月 19 19:45 2013 tweet.frm
83546619

$ ls -l mroonga_wrapper* | tee >(awk '{i+=$5}END{print i}')
-rw-rw---- 1 mysql mysql     4096  8月 19 19:45 2013 mroonga_wrapper.mrn
-rw-rw---- 1 mysql mysql 17051648  8月 19 19:45 2013 mroonga_wrapper.mrn.0000000
-rw-rw---- 1 mysql mysql 16842752  8月 19 19:45 2013 mroonga_wrapper.mrn.0000104
-rw-rw---- 1 mysql mysql  8437760  8月 19 19:45 2013 mroonga_wrapper.mrn.0000105
-rw-rw---- 1 mysql mysql  7639040  8月 19 19:45 2013 mroonga_wrapper.mrn.0000106
-rw-rw---- 1 mysql mysql 12587008  8月 19 19:45 2013 mroonga_wrapper.mrn.0000106.c
-rw-rw---- 1 mysql mysql  1048576  8月 19 19:45 2013 mroonga_wrapper.mrn.001

mroonga_wrapper:
合計 1464
-rw-rw---- 1 mysql mysql      61  8月 19 19:38 2013 db.opt
-rw-rw---- 1 mysql mysql 1263404  8月 19 19:45 2013 tweet.MYD
-rw-rw---- 1 mysql mysql  217088  8月 19 19:45 2013 tweet.MYI
-rw-rw---- 1 mysql mysql    8638  8月 19 19:45 2013 tweet.frm
65100071
SHOW TABLE STATUSには計上されないんだね。。容量の増加量はストレージモードで23MiB, ラッパーモードで48MiBくらい。

TokenBigramのトークン数はフルテキスト文字数とイコールで、SUM(CHARACTER_LENGTH(text))で取ったら504972だったので、トークンは概算で50万とする。アルファベットはまとめて1つのトークンにするとかそういうのは取り敢えず今は考えない。
⇒本当はSUM(CHARACTER_LENGTH(text) - 1)になるかと思ったんだけど、ならないみたい。
http://groonga.org/docs/spec/search.html

1トークンあたりのサイズは(2 * charset + PRIMARY KEY SIZE)くらいかなと期待すると、utf8は1文字3バイトでPRIMARY KEYがBIGINTの8バイトで16バイト。

単純に掛け算すると8MiBくらいが期待だったんだけど、とてもそんなもんじゃ済んでない。単純にLOAD DATAしただけでも60MiB食うような感じだから、内部的に色々情報を持っててこれじゃ済まないってことなんだろうけど。

取り敢えず思ったより行くよね、というところに止めておいて他の何かで追試したい。というか、してくる。


TokenMecabでどのくらい減らせるかも調べたい。。

0 件のコメント :

コメントを投稿