Tasuku SUENAGA
a****@razil*****
2007年 6月 25日 (月) 19:55:52 JST
未来検索ブラジルの末永です。 複数カラムを対象としたOR検索が遅い件についてです。 ●解決方法1 まず、TAB1の定義を以下のように変更します。 CREATE TABLE TAB1 (COL1 TEXT, COL2 TEXT, FULLTEXT(COL1, COL2)); そして、 SELECT * FROM TAB1 WHERE MATCH(COL1, COL2) AGAINST('検索語'); を実行すると所望の結果が得られます。 現在のTritonnの実装では、複数のカラムに対してインデックスを作成した場合、 SELECT CONCAT(COL2, " ", COL1) AS COL FROM TAB1; で取得できる値COLをインデックスの対象にします。 (インデックス定義時のカラムの順番に対して逆順で連結しています) よって、COL1とCOL2に対してインデックスを作成して、 それに対して検索をかけることで、 COL1またはCOL2に検索単語が存在するレコードが取得できます。 ●解決方法2 UNIONで高速ということであれば、 もしかしたら以下のクエリで速度が上がる可能性があります。 SELECT * FROM TAB1 FORCE INDEX (PRIMARY) WHERE MATCH(COL1) AGAINST ('検索語') OR MATCH(COL2) AGAINST ('検索語'); なお、この場合はSennaが2回呼ばれてしまうので、 解決方法1よりも速度が劣ると思います。 ●メモ 一般的にOR検索は検索結果が増えてしまうので、 処理速度が遅くなる傾向にあります。 たとえば、 SELECT * FROM TAB1 WHERE MATCH(COL1) AGAINST('未来 検索' IN BOOLEAN MODE); と SELECT * FROM TAB1 WHERE MATCH(COL1) AGAINST('*D+未来 検索' IN BOOLEAN MODE); では後者のほうが速く検索することができます。 Yuki Horikoshi さんは書きました: > 皆様はじめまして。堀越と申します。 > > 実験的にtritonn-1.0.2.mysql-5.0.41.senna-1.0.5を利用させて頂いております。 > 複数カラムに対するOR検索にて顕著なパフォーマンスの悪化がありましたので > レポート・質問させてください。 > > CREATE TABLE TAB1 (COL1 TEXT,COL2 TEXT,FULLTEXT(COL1),FULLTEXT(COL2)); > のようなテーブルに65万件の日本語データを投入しました。 > 以下はshow senna statusの結果です。 > > (中略) > > このデータに対して以下のクエリを投げました。 > > ■単一カラムに対する検索の比較 > SELECT * FROM TAB1 WHERE COL1 LIKE '%検索語%'; (1.11sec) > SELECT * FROM TAB1 WHERE MATCH(COL1) AGAINST ('検索語'); (0.01sec) > 素晴らしい結果です。 > > ■複数カラムに対するAND検索の比較 > SELECT * FROM TAB1 WHERE COL1 LIKE '%検索語%' AND COL2 LIKE '%検索語%'; (1.10sec) > SELECT * FROM TAB1 WHERE MATCH(COL1) AGAINST ('検索語') AND MATCH(COL2) AGAINST ('検索語'); (0.06sec) > これも素晴らしい。 > > ■複数カラムに対するOR検索の比較 > SELECT * FROM TAB1 WHERE COL1 LIKE '%検索語%' OR COL2 LIKE '%検索語%'; (1.24 sec) > SELECT * FROM TAB1 WHERE MATCH(COL1) AGAINST ('検索語') OR MATCH(COL2) AGAINST ('検索語'); (3.68sec) > > なぜか複数カラムに対するOR検索だけがパフォーマンスが悪いようです。 > これはこういった物なのでしょうか? > > Senna-dev569-585の池田様・うただ様のやりとりにあったように > show status like 'handle%';,vmstatも取得してみましたが、 > like検索時とmatch-against検索時で同等の結果でした。 > > ちなみに、的外れかもしれませんが、 > ■UNIONクエリによる結合の比較 > (SELECT * FROM TAB1 WHERE COL1 LIKE '%検索語%') UNION (SELECT * FROM TAB1 WHERE COL2 LIKE '%検索語%'); (1.99sec) > (SELECT * FROM TAB1 WHERE MATCH(COL1) AGAINST ('検索語')) UNION (SELECT * FROM TAB1 WHERE MATCH(COL2) > AGAINST ('検索語'));(0.06sec) > として上記遅延の回避はできましたが・・ > > また、ngram・mecabのどちらでも同様の結果でした。 > 問題点や解決法などあればご教示頂ければ幸いです。 > 何卒宜しくお願いいたします。 > > --- > Yuki Horikoshi <horik****@maste*****> --- Tasuku SUENAGA <a****@razil*****>