[groonga-dev, 02987] better estimation of rows possible in Mroonga ?

Back to archive index

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側でいい感じの順で評価して
くれると思うのですが、こういうことは可能でしょうか?

どうぞよろしくお願いします。

かずひこ




groonga-dev メーリングリストの案内
Back to archive index