5.1. 最適化 — Mroonga vmrn_version documentation

本文へスキップ
`Ctrl`+`K`

# 5.1. 最適化

Mroongaはより速くレスポンスを返すためにいくつか最適化しています。

いくつかの最適化は ストレージモード でだけ有効です。

## 5.1.1. 必要なカラムだけ取得

この最適化は ストレージモード でだけ有効です。

Groongaはカラム（列）ストアアーキテクチャーを採用しています。これは、1行の1つのカラムの値を取得するために、すべてのカラムの値を取得しなくてもよいということです。Groongaは必要なカラムの値だけを取得できます。

InnoDBとMyISAMはロー（行）ストアアーキテクチャーを採用しています。InnoDBとMyISAMは、1行の1つのカラムの値が必要な場合でもすべてのカラムの値を取得する必要があります。

`SELECT` で必要なカラムだけを指定した場合、Mroongaは指定されたカラムの値だけを取得します。Mroongaは他のカラムの値を取得しません。

Mroongaは処理とI/Oを減らすことでより高速になります。

これがこの最適化です。

以下はこの最適化を説明するためのテーブル定義です。:

    CREATE TABLE t1 (
      c1 INT PRIMARY KEY AUTO_INCREMENT,
      c2 INT,
      c3 INT,
      ...
      c11 VARCHAR(20),
      c12 VARCHAR(20),
      ...
      c20 DATETIME
    ) ENGINE=Mroonga DEFAULT CHARSET=utf8;

以下はこの最適化を説明するための `SELECT` です。:

    SELECT c1, c2, c11 FROM t1 WHERE c2 = XX AND c12 = "XXX";

このケースではMroongaは `c1` 、 `c2` 、 `c11` 、 `c12` カラムの値だけを取得します。 `c3` 、 `c4` 、 ...、 `c10` 、 `c13` 、 ...、 `c19` 、`c20` カラムの値は取得しません。

## 5.1.2. 行カウント

この最適化は ストレージモード でだけ有効です。

MySQLは `COUNT(*)` を処理する時、カラムの値が必要ないにも関わらず、ストレージエンジンモジュールにすべてのカラムの値を要求します。

この場合、Mroongaはカラムの値を取得しません。

Mroongaは処理とI/Oを減らすことでより高速になります。

これがこの最適化です。

以下はこの最適化を説明するための `SELECT` です。:

    SELECT COUNT(*) FROM t1 WHERE MATCH(c2) AGAINST("+keyword" IN BOOLEAN MODE);

この `SELECT` は `COUNT(*)` だけを取得し、 `WHERE` の条件はインデックスだけで処理できます。この場合、Mroongaはこの最適化を使います。

この最適化が使われたかどうかは Mroonga_count_skip ステータス変数を参照するとわかります。:

    mysql> SHOW STATUS LIKE 'Mroonga_count_skip';
    +--------------------+-------+
    | Variable_name      | Value |
    +--------------------+-------+
    | Mroonga_count_skip | 1     |
    +--------------------+-------+
    1 row in set (0.00 sec)

Mroonga_count_skip ステータス変数の値はMroongaがこの最適化を使うとインクリメントされます。

mroonga_enable_optimization に `false` を指定するとこの最適化を無効にできます。

## 5.1.3. `ORDER BY LIMIT`

この最適化は ストレージモード と ラッパーモード 両方で有効です

MySQLは、ヒットレコード数が多くても、インデックスを使ってソート済みの結果を取得できるなら `ORDER BY` と `LIMIT` を少ないコストで処理できます。

MySQLは `MATCH() AGAINST(IN NATURAL LANGUAGE MODE)` でこの処理を使えますが、 `MATCH() AGAINST(IN BOOLEAN MODE)` では使えません。

これは、多くのレコードがマッチする `MATCH() AGAINST(IN BOOLEAN MODE)` には時間がかかる可能性があるということです。

MroongaはGroongaを使って `ORDER BY` と `LIMIT` を処理し、MySQLには処理対象のレコードだけを返します。マッチレコード数が多いとき、MySQLで処理するよりもGroongaで処理する方が非常に高速です。

これがこの最適化です。

以下はこの最適化を説明するための `SELECT` です。:

    SELECT *
      FROM t1
     WHERE MATCH(c2) AGAINST("+keyword" IN BOOLEAN MODE)
     ORDER BY c1 LIMIT 1;

この `SELECT` は全文検索とソートをGroongaで実行し、MySQLには1件のレコードのみ返します。

この最適化が使われたかどうかは Mroonga_fast_order_limit ステータス変数を参照するとわかります。:

    mysql> SHOW STATUS LIKE 'Mroonga_fast_order_limit';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | Mroonga_fast_order_limit | 1     |
    +--------------------------+-------+
    1 row in set (0.00 sec)

Mroonga_fast_order_limit ステータス変数はMroongaがこの最適化を使うとインクリメントされます。

この最適化は以下のすべての条件が真のときだけ使われます。

- ストレージモード ： `WHERE` 節にある条件が1つの `MATCH AGAINST` と0個以上の算術演算だけのとき。算術演算とは `column < 100` のような演算です。

- ラッパーモード ： `WHERE` 節にある条件が `MATCH AGAINST` だけのとき。

- `JOIN` がない。

- `GROUP BY` がない。

- `SQL_CALC_FOUND_ROWS` がない。

- `LIMIT` がある。

- ストレージモード ： `ORDER BY` 節にはカラムまたは `WHERE` 節で使っているものと同じ `MATCH AGAINST` しかない。

- ラッパーモード ： `ORDER BY` 節にはプライマリキーまたは `WHERE` 節で使っているものと同じ `MATCH AGAINST` しかない。