Kazuhiko
kazuh****@fdiar*****
2014年 11月 27日 (木) 00:28:14 JST
こんにちは、かずひこです。 Mroongaによる全文検索で、EXPLAINで見えるRowsの値が常に1なのですが、これ をある程度それっぽい値にすることは可能でしょうか? それによって、複数の 全文検索クエリのあるクエリの実行速度の改善を図りたい、というのが背景です。 (以下、MariaDB 10.0.15, Groonga 4.0.7, Mroonga 4.07) CREATE TABLE catalog ( uid bigint(20) unsigned NOT NULL, path varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (uid) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE catalog_full_text ( uid bigint(20) unsigned NOT NULL, title varchar(255) COLLATE utf8_unicode_ci DEFAULT '', PRIMARY KEY (uid), FULLTEXT KEY title (title) COMMENT 'parser "TokenBigramSplitSymbolAlphaDigit"' ) ENGINE=Mroonga DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE category ( uid bigint(20) unsigned NOT NULL, category_uid bigint(20) unsigned NOT NULL DEFAULT '0', base_category_uid bigint(20) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (uid,category_uid,base_category_uid) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; というテーブル群に対して、 SELECT DISTINCT catalog.path, catalog.uid, MATCH (title_full_text.title) AGAINST ('*D+ foo' IN BOOLEAN MODE) AS title__score__ FROM ( ( catalog AS catalog INNER JOIN ( category AS category INNER JOIN catalog_full_text AS source_title_full_text ON category.base_category_uid = 18482 AND source_title_full_text.uid = category.category_uid ) ON category.uid = catalog.uid ) INNER JOIN catalog_full_text AS title_full_text ON title_full_text.uid = catalog.uid ) WHERE MATCH (source_title_full_text.title) AGAINST ('*D+ bar' IN BOOLEAN MODE) AND MATCH (title_full_text.title) AGAINST ('*D+ foo' IN BOOLEAN MODE) というクエリを実行すると、EXPLAINの結果はこうなります。 *************************** 1. row *************************** id: 1 select_type: SIMPLE table: source_title_full_text type: fulltext possible_keys: PRIMARY,title key: title key_len: 0 ref: rows: 1 Extra: Using where with pushed condition; Using temporary *************************** 2. row *************************** id: 1 select_type: SIMPLE table: title_full_text type: fulltext possible_keys: PRIMARY,title key: title key_len: 0 ref: rows: 1 Extra: Using where with pushed condition *************************** 3. row *************************** id: 1 select_type: SIMPLE table: catalog type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 8 ref: test.title_full_text.uid rows: 1 Extra: *************************** 4. row *************************** id: 1 select_type: SIMPLE table: category type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 24 ref: test.title_full_text.uid,test.source_title_full_text.uid,const rows: 1 Extra: Using index; Distinct 先頭から、全文検索クエリが二つ来て、そのどちらもrowsが1になっています。 このクエリがすごく遅いケースがあって調べてみると、一つ目の全文検索クエリ にマッチするのが25316件で、二つ目の全文検索クエリにマッチするのが1631件 でした。 試しにINNER JOINの順序を動かして、件数が少ない方のJOINを先頭にしてみると かなり速くなりました。 MroongaからMariaDBに渡る件数の見積もりが、常に1ではなく、ある程度それっ ぽい数字にできれば、クエリはそのままでMariaDB側でいい感じの順で評価して くれると思うのですが、こういうことは可能でしょうか? どうぞよろしくお願いします。 かずひこ