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側でいい感じの順で評価して
くれると思うのですが、こういうことは可能でしょうか?
どうぞよろしくお願いします。
かずひこ