2014年3月4日火曜日

Mroongaのテーブルからノイズになるトークンを(手で)取り除いてみる

データは 日々の覚書: 全文検索のテスト用にtweets.csvを食わせるSQL で書いた、わたしのツイートをテーブルに突っ込んだもので試してみました。

トークナイザーとノーマライザーはデフォルトの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トークン程度では)わざわざやる必要なし。

本番データで試したくなってきました。

0 件のコメント :

コメントを投稿