データは 日々の覚書: 全文検索のテスト用にtweets.csvを食わせるSQL で書いた、わたしのツイートをテーブルに突っ込んだもので試してみました。
トークナイザーとノーマライザーはデフォルトのTokenBigram, NormalizerMySQLGeneralCIにそれぞれなっています。
たぶん中の人には嫌われるでしょうが、わたしは--output_type tsv好きですよ :)
では早速トークンを覗き込んでみる。
いかにもノイズっぽいのがいっぱいありますね!
あ、"index""tweets"のカラム(3カラム目の、数字が並んでるやつ)は、そのトークンを持ってるレコードの数とかじゃないのでご注意を。
もとの速度は
まあこんなもんとしておきます。
とまあ、要らなさそうなトークンを選んで消していきます。他にも記号だけで構成されたトークンとかいろいろゴニョゴニョがんばって消してみました。どうか。
うん、誤差!
プロファイルのDurationを足し合わせると2回目の方がほんの少し小さいのに、"2778 rows in set"のあとの数字は2回目の方が大きいふしぎ!
そこはそれとして、さらに、アルファベットのみで構成されたトークン以外を全部消してみた。
プロファイルのDurationの合計、もともと 27.892ms, ノイズ削除 26.713ms, アルファベット以外全部削除 25.746ms。
結論、効果はあるんだろうけど(少なくとも16000レコードちょっと、51000トークン程度では)わざわざやる必要なし。
本番データで試したくなってきました。
トークナイザーとノーマライザーはデフォルトのTokenBigram, NormalizerMySQLGeneralCIにそれぞれなっています。
$ /usr/groonga/4.0.0/bin/groonga /usr/mysql/5.6.16/data/mroonga.mrn
> table_list --output_type tsv
0 1393927353.03097 0.000258684158325195
"id""UInt32"
"name""ShortText"
"path""ShortText"
"flags""ShortText"
"domain""ShortText"
"range""ShortText"
"default_tokenizer""ShortText"
"normalizer""ShortText"
259
"tweets"
"/usr/mysql/5.6.16/data/mroonga.mrn.0000103"
"TABLE_PAT_KEY|PERSISTENT"
"UInt64"
263
"tweets-text"
"/usr/mysql/5.6.16/data/mroonga.mrn.0000107"
"TABLE_PAT_KEY|PERSISTENT"
"ShortText"
"TokenBigram"
"NormalizerMySQLGeneralCI"
END
たぶん中の人には嫌われるでしょうが、わたしは--output_type tsv好きですよ :)
では早速トークンを覗き込んでみる。
> select tweets-text --output_type tsv
0 1393927720.5169 0.000890493392944336
51762
[ "_id""UInt32" ] [ "_key""ShortText" ] [ "index""tweets" ]
26653 "\t" 45
44250 "\tな" 1
15055 "\tを" 1
4 "\n" 944
3 "\n\n" 945
11621 "\nあ" 60
3101 "\nい" 23
14566 "\nう" 21
5776 "\nえ" 1
11625 "\nお" 77
END
いかにもノイズっぽいのがいっぱいありますね!
あ、"index""tweets"のカラム(3カラム目の、数字が並んでるやつ)は、そのトークンを持ってるレコードの数とかじゃないのでご注意を。
もとの速度は
mysql56> pager cat > /dev/null
PAGER set to 'cat > /dev/null'
mysql56> SELECT * FROM tweets WHERE MATCH(text) AGAINST ('+MySQL' IN BOOLEAN MODE);
2778 rows in set (0.02 sec)
mysql56> nopager
PAGER set to stdout
mysql56> SHOW PROFILE;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000055 |
| Waiting for query cache lock | 0.000007 |
| init | 0.000006 |
| checking query cache for query | 0.000131 |
| checking permissions | 0.000016 |
| Opening tables | 0.000115 |
| init | 0.000084 |
| System lock | 0.000030 |
| optimizing | 0.000019 |
| statistics | 0.000663 |
| preparing | 0.000036 |
| FULLTEXT initialization | 0.003164 |
| executing | 0.000021 |
| Sending data | 0.019530 |
| end | 0.000027 |
| query end | 0.000012 |
| closing tables | 0.000177 |
| freeing items | 0.003743 |
| cleaning up | 0.000056 |
+--------------------------------+----------+
19 rows in set, 1 warning (0.00 sec)
まあこんなもんとしておきます。
$ /usr/groonga/4.0.0/bin/groonga /usr/mysql/5.6.16/data/mroonga.mrn "select tweets-text --output_type tsv --limit -1" | perl -nlae 'if (@F[1] =~ /\\/) {my $cmd= sprintf("/usr/groonga/4.0.0/bin/groonga /usr/mysql/5.6.16/data/mroonga.mrn \"delete tweets-text --output_type tsv --filter \\\"_id== %d\\\"\"", @F[0]); system($cmd);}'
..
とまあ、要らなさそうなトークンを選んで消していきます。他にも記号だけで構成されたトークンとかいろいろゴニョゴニョがんばって消してみました。どうか。
mysql56> pager cat > /dev/null
PAGER set to 'cat > /dev/null'
mysql56> SELECT * FROM tweets WHERE MATCH(text) AGAINST ('+MySQL' IN BOOLEAN MODE);
2778 rows in set (0.03 sec)
mysql56> nopager
PAGER set to stdout
mysql56> SHOW PROFILE;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000045 |
| Waiting for query cache lock | 0.000009 |
| init | 0.000006 |
| checking query cache for query | 0.000099 |
| checking permissions | 0.000012 |
| Opening tables | 0.000119 |
| init | 0.000054 |
| System lock | 0.000019 |
| optimizing | 0.000022 |
| statistics | 0.000623 |
| preparing | 0.000033 |
| FULLTEXT initialization | 0.003134 |
| executing | 0.000018 |
| Sending data | 0.019653 |
| end | 0.000038 |
| query end | 0.000012 |
| closing tables | 0.000199 |
| freeing items | 0.002571 |
| cleaning up | 0.000047 |
+--------------------------------+----------+
19 rows in set, 1 warning (0.00 sec)
うん、誤差!
プロファイルのDurationを足し合わせると2回目の方がほんの少し小さいのに、"2778 rows in set"のあとの数字は2回目の方が大きいふしぎ!
そこはそれとして、さらに、アルファベットのみで構成されたトークン以外を全部消してみた。
mysql56> pager cat > /dev/null
PAGER set to 'cat > /dev/null'
mysql56> SELECT * FROM tweets WHERE MATCH(text) AGAINST ('+MySQL' IN BOOLEAN MODE);
2778 rows in set (0.02 sec)
mysql56> nopager
PAGER set to stdout
mysql56> SHOW PROFILE;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000050 |
| Waiting for query cache lock | 0.000006 |
| init | 0.000007 |
| checking query cache for query | 0.000104 |
| checking permissions | 0.000013 |
| Opening tables | 0.000055 |
| init | 0.000055 |
| System lock | 0.000021 |
| optimizing | 0.000018 |
| statistics | 0.000387 |
| preparing | 0.000032 |
| FULLTEXT initialization | 0.002243 |
| executing | 0.000021 |
| Sending data | 0.018932 |
| end | 0.000027 |
| query end | 0.000012 |
| closing tables | 0.000175 |
| freeing items | 0.003542 |
| cleaning up | 0.000046 |
+--------------------------------+----------+
19 rows in set, 1 warning (0.00 sec)
プロファイルのDurationの合計、もともと 27.892ms, ノイズ削除 26.713ms, アルファベット以外全部削除 25.746ms。
結論、効果はあるんだろうけど(少なくとも16000レコードちょっと、51000トークン程度では)わざわざやる必要なし。
本番データで試したくなってきました。