1. 最適化

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

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

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は c1c2c11c12 カラムの値だけを取得します。 c3c4 、 ...、 c10c13 、 ...、 c19c20 カラムの値は取得しません。

1.2. 行カウント

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

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

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

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

これがこの最適化です。

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

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

この SELECTCOUNT(*) だけを取得し、 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_optimizationfalse を指定するとこの最適化を無効にできます。

1.3. ORDER BY LIMIT

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

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

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

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

MroongaはGroongaを使って ORDER BYLIMIT を処理し、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 しかない。