[groonga-dev,01766] Re: 仮想メモリサイズを超えるmroongaのインデックス構築について

Back to archive index

Naoya Murakami visio****@gmail*****
2013年 9月 6日 (金) 12:51:18 JST


お世話になっております。村上です。

>トークンの最大出現回数に違いはありそうですか?例えば、1つの文
>書に「the」がたくさんあり、さらに多くの文書が同じように「the」
>をたくさん含んでいる、というようなことがあるかどうかです。

>↑はGRN_II_MAX_TFが関連してくる値なのですが、GRN_II_MAX_TFを
>大きくしたためにデータが壊れているのではないか、というのが気
>になりました。

懸念点のご提示ありがとうございます!助かります。

インデックス構築ができていないですし、ちょっと調べる方法がないので
具体的にはわからないですが、英語の方が出現回数が多いようなイメージ
はあります。「the」等は多いでしょうね。日本語は、前記等はわざわざ書かない
ことがほとんどでしょうし。
日本語のバイグラムトークンの場合は、単語が欠ける惧れがありますが、
英語の場合、原則、空白区切りになりますし、出現回数が極端に多いものは、
あっても検索速度が遅くなる等、害になるだけなので、GRN_II_MAX_TFを
デフォルトに戻してみて、再現するか試してみようと思います。

また、別の話になるのですが日本語のデータベースの性能を試したところ、
バイグラムトークンということもあって、語彙数が多すぎて、
クエリによってはやや苦しい感じでした。(実行時間:1〜10秒)

そこで、性能を向上させるために、語彙数を抑えるようトークナイズ処理の
最適化をする必要があるなぁと思っています。

結構、造語とか複合名詞が多い文章なので、Mecabを使うのもなかなか調整が
難しいのですが、ノイズは増えてもいいので、漏れが減るようできるだけ
短い単語で区切られるよう辞書を調整するとか、てにをは等の一般的な用語を
減らせるようストップワードのようなフィルタ処理を追加する等、検討して
みたいと思います。
ストップワードの処理は英語にも適用できるので、英語のデータベースでも
速度向上できるかなぁと思ってます。
(あまりプログラミング能力はないので、いいものが作れる自身はありませんが
とりあえず動くものを作れればいいなぁ。)

こうすると、原則単語でトークナイズされて出現回数が多いものが除かれ、
GRN_II_MAX_TFをあげる必要もないかなぁと思っています。


以下は、実行時間結果です。ご参考まで。

-----------------------
mysql> select count(*) from ftext where match(title,abstract,claims)
against('+データベース description_198x:@データベース
description_199x:@データベースdescription_200x:@データベースdescription_201x:@データベース'
in boolean mode) limit 1;
+----------+
| count(*) |
+----------+
|   330272 |
+----------+
1 row in set (2.44 sec)
マルチカラムインデックスが作れなかったので、SQLで書こうとすると、
後ろにgroongaのクエリー構文をつける方法しかつかえない。
また、この場合、重み付けも使えない。

mysql> SHOW STATUS LIKE 'Mroonga_count_skip';;
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| Mroonga_count_skip | 1     |
+--------------------+-------+
1 row in set (0.00 sec)

mysql> select app_id from ftext where match(title,abstract,claims)
against('+データベース description_198x:@データベース
description_199x:@データベースdescription_200x:@データベースdescription_201x:@データベース'
in boolean mode) order by pub_date desc limit 1;
+---------------+
| app_id        |
+---------------+
| JP20110554016 |
+---------------+
1 row in set (2.47 sec)

mysql> SHOW STATUS LIKE 'Mroonga_fast_order_limit';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| Mroonga_fast_order_limit | 1     |
+--------------------------+-------+
1 row in set (0.00 sec)

mysql> select count(app_id) from ftext where match(title,abstract,claims)
against('+データベース description_198
x:@データベース description_199x:@データベース
description_200x:@データベースdescription_201x:@データベース'
in
 boolean mode) limit 1;
+---------------+
| count(app_id) |
+---------------+
|        330272 |
+---------------+
1 row in set (5.11 sec)
count最適化がきかない例。

mysql> select mroonga_command('select ftext --match_columns
title||abstract||claims||description_198x||description_199x||description_200x||description_201x
--query "+データベース" --output_columns app_id --sortby -pub_date --limit 1') as
result;
+---------------------------------------------------------+
| result                                                  |
+---------------------------------------------------------+
| [[[330272],[["app_id","ShortText"]],["JP20110554016"]]] |
+---------------------------------------------------------+
1 row in set (2.46 sec)
こっちだと、カウントとデータ取得の計2回やらなくてすみますし、重み付けも
ドリルダウンもつかえるので、こっちでやろうと思ってます。
groongaだと件数とデータを同時に取れるみたいなので、mysqlからも
FOUND_ROWS()とかのように件数とデータが1回で取れるようになると
便利そうだなぁと思いました。

mysql> select mroonga_command('select ftext --match_columns
title||abstract||claims||description_198x||description_199x||description_200x||description_201x
--query "+データ" --output_columns app_id --sortby -pub_date --limit
 1') as result;
+----------------------------------------------------------+
| result                                                   |
+----------------------------------------------------------+
| [[[2514795],[["app_id","ShortText"]],["JP20110516905"]]] |
+----------------------------------------------------------+
1 row in set (6.73 sec)
クエリによっては結構遅くなる。件数が多いと時間がかかる?

mysql> select mroonga_command('select ftext --match_columns
title||abstract||claims||description_198x||description_199x||description_200x||description_201x
--query "+デー" --output_columns app_id --sortby -pub_date --limit 1
') as result;
+----------------------------------------------------------+
| result                                                   |
+----------------------------------------------------------+
| [[[2602550],[["app_id","ShortText"]],["JP20100544917"]]] |
+----------------------------------------------------------+
1 row in set (1.01 sec)
こっちは件数が増えたにもかかわらず速い。単純な件数の問題ではない?
検索するトークンが減ったからかなぁ。。
でも検索トークン数の多い「データベース」のが「データ」より速いなぁ。。


mysql> select mroonga_command('select ftext --match_columns
title||abstract||claims||description_198x||description_199x||description_200x||description_201x
--query "+database" --output_columns app_id --sortby pub_date --limit 1')
as result;
+-------------------------------------------------------+
| result                                                |
+-------------------------------------------------------+
| [[[5357],[["app_id","ShortText"]],["JP20120546657"]]] |
+-------------------------------------------------------+
1 row in set (0.04 sec)
日本語のDBなので、英単語の出現回数は少なく、また、バイグラムでなく単語単位で
トークナイズされているので非常に速い?


以上、よろしくお願いします。





groonga-dev メーリングリストの案内
Back to archive index