Mroongaのラッパーモードで検索が遅いSQLを作ってしまった話

SQLの組み立て方によってmroonga(ラッパーモード)でのSQL

重くなってしまった話。

SQLとデータ件数については記事の都合簡略&省略してますが、実際流したときは、だいたいtextAの件数が40万件で、testBのデータ件数が2000件ぐらい。

 

testAテーブル

CREATE TABLE `testA` (
  `id` varchar(32) NOT NULL,
  `title` varchar(52) NOT NULL DEFAULT '',
  `text` text NOT NULL,
   PRIMARY KEY (id),
   FULLTEXT INDEX content_index (title, text) COMMENT 'parser "TokenMecab", normalizer "NormalizerMySQLUnicodeCIExceptKanaCIKanaWithVoicedSoundMark"'
) ENGINE=mroonga DEFAULT CHARSET=utf8 COMMENT='engine "innodb"';

idにはインデックスはってます。

-------------------------------------------------------

|id|title|text|
|1|テスト|都内で事故が起きました|
|2|テスト2|今夜のTVニュース|
|3|テスト3|明日の天気|
-------------------------------------
testBテーブル
-------------------------------------
|uid|id|flag|
|u1|1|0|
|u2|2|1|
|u1|3|0|
---------------------------------------
create tableは省略。uidとidにインデックスはってる。

取得要件
testBテーブルのuidがu1かつflagが0のデータのidに一致する
testAのテーブルのデータでもって、'事故'という検索語で全文検索を行う

遅くなってしまったSQL

select
    id, title,text
from
    testA
where
    testA.id in (SELECT
            id
        FROM
            testB
        WHERE
            testB.uid = 'u1' and testB.flag = 0)
      and MATCH (testA.title , testA.text) AGAINST ('+事故' IN BOOLEAN MODE)

 

改善したSQL

SELECT
    id, title, text
FROM
    testB
    left join textA ON testB.id = testA.id
WHERE
    testB.uid = 'u1' and testB.flag = 0
        and MATCH (testA.title, testA.text) AGAINST ('+事故' IN BOOLEAN MODE)

 

改善したSQLのが劇的に早かった。

書き方的にjoinしたテーブルに全文検索できると思っておらず・・・

遅いSQLでは、in句で対象を絞った後に、全文検索してくれるのかなと

勝手に思ってしまったOTZ

実際実行のときどういう条件で判断されるかいまいちなので、知識不足が否めない。

 

ちなみにEXPLAIN見たら、遅いSQLのときはfulltextしてたのに

改善SQLではfulltextしてなかった。

よくわからん。