Kouhei Sutou
kou****@clear*****
2013年 12月 5日 (木) 15:16:43 JST
須藤です。 In <CAKRtL1u=fGRGxvysCjf1w1DSKaa_VxmzdZBy_A9p+0****@mail*****> "[groonga-dev,01940] FULLTEXTインデックス以外での絞り込みについて" on Wed, 4 Dec 2013 18:32:56 +0900, Horikoshi Yuki <horik****@gmail*****> wrote: > FULLTEXTインデックスでの全文検索自体は非常に高速に動いているのですが、 > 掲題の通りFULLTEXTインデックス以外での絞り込みを利用した際、 > 全文検索でのヒット件数が多い場合(数千件〜)に速度が遅くなってしまいます。 うーん、手元のふつうのPC(メモリー8GB)では再現しませんでし た。(xxxというテーブル名にしました。) mysql> SHOW CREATE TABLE xxx\G *************************** 1. row *************************** Table: xxx Create Table: CREATE TABLE `xxx` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` text, `birth_year` smallint(5) unsigned DEFAULT NULL, PRIMARY KEY (`id`), KEY `birth_year` (`birth_year`), FULLTEXT KEY `name` (`name`) ) ENGINE=mroonga AUTO_INCREMENT=10000001 DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> SELECT COUNT(*) FROM xxx; +----------+ | COUNT(*) | +----------+ | 10000000 | +----------+ 1 row in set (0.00 sec) mysql> SELECT COUNT(*) FROM xxx WHERE MATCH(name) AGAINST ("山田"); +----------+ | COUNT(*) | +----------+ | 1000000 | +----------+ 1 row in set (0.31 sec) mysql> SELECT COUNT(*) FROM xxx WHERE birth_year > 1973; +----------+ | COUNT(*) | +----------+ | 4996106 | +----------+ 1 row in set (1.24 sec) mysql> SELECT COUNT(*) FROM xxx WHERE MATCH(name) AGAINST ("山田") AND birth_year > 1973; +----------+ | COUNT(*) | +----------+ | 500510 | +----------+ 1 row in set (1.17 sec) mysql> SELECT COUNT(*) FROM xxx WHERE MATCH(name) AGAINST ("山田") AND birth_year > 1973 ORDER BY birth_year LIMIT 0,50; +----------+ | COUNT(*) | +----------+ | 500510 | +----------+ 1 row in set (1.18 sec) ↑ではCOUNT(*)でやっていますが、*でやっても同じくらいの速度 でした。 で、それはそれとして。。。 > おそらく、この事象については以下のチケット > http://redmine.groonga.org/issues/447 > に記載された内容だと思うのですが、現状mroongaで回避策などはありますか? > (チケット発行日が3年前でしたので、既に解決済みであれば申し訳ありません) ここに書かれていることを実現する仕組みがすでにMroongaには入っ ているのです! ただ、それぞれの演算子に対して実施する必要があって、今はすべ ての処理に対応しているわけではありません。今は、 MATCH AGAINST AND INT系のカラム = 数値 ORDER BY LIMIT; か MATCH AGAINST AND 文字列系のカラム = 文字列 ORDER BY LIMIT; のときのみ効きます。 http://mroonga.org/ja/docs/userguide/storage.html#optimisation-for-order-by-limit-in-full-text-search をより進めた機能なのですが、ドキュメントが追いついていません ね。。。 ただし!今回のように INT系のカラム < 数値 には対応していなかったのでリポジトリーの方では対応しておきま した。 もし、 SELECT * FROM 名簿 WHERE MATCH(NAME) AGAINST ("山田") AND birth_year = 1973; では遅いままで、ORDER BY LIMITを付けて SELECT * FROM 名簿 WHERE MATCH(NAME) AGAINST ("山田") AND birth_year = 1973 ORDER BY birth_year LIMIT 0,50; とすると速くなるのであれば、次のリリースを使えば高速になると 思います! > 大変お恥ずかしい話なのですが、未だこの問題の解決方法が見つけられず > senna + tritonnからの移行が出来ておりません・・・・ 次のリリースで移行できるはずです! -- 須藤 功平 <kou****@clear*****> 株式会社クリアコード <http://www.clear-code.com/> (03-6231-7270) Groongaサポート: http://groonga.org/ja/support/ パッチ採用はじめました: http://www.clear-code.com/recruitment/ コミットへのコメントサービスはじめました: http://www.clear-code.com/services/commit-comment.html