MySQL 8.0 リファレンスマニュアル MySQL NDB Cluster 8.0 を含む

このページは機械翻訳したものです。

8.9.6 オプティマイザ統計

column_statistics データディクショナリテーブルには、オプティマイザがクエリー実行計画を作成するために使用する、カラム値に関するヒストグラム統計が格納されます。 ヒストグラム管理を実行するには、ANALYZE TABLE ステートメントを使用します。

column_statistics テーブルには、次の特性があります:

column_statistics テーブルはデータディクショナリの一部であるため、ユーザーは直接アクセスできません。 ヒストグラム情報は、データディクショナリテーブルのビューとして実装されている INFORMATION_SCHEMA.COLUMN_STATISTICS を使用して入手できます。 COLUMN_STATISTICS には、次のカラムがあります:

カラムヒストグラムには、カラムに格納されている値の範囲の一部のバケットが含まれます。 ヒストグラムは、カラム統計の柔軟な表現を可能にする JSON オブジェクトです。 ヒストグラムオブジェクトのサンプルを次に示します:

{
  "buckets": [
    [
      1,
      0.3333333333333333
    ],
    [
      2,
      0.6666666666666666
    ],
    [
      3,
      1
    ]
  ],
  "null-values": 0,
  "last-updated": "2017-03-24 13:32:40.000000",
  "sampling-rate": 1,
  "histogram-type": "singleton",
  "number-of-buckets-specified": 128,
  "data-type": "int",
  "collation-id": 8
}

ヒストグラムオブジェクトには、次のキーがあります:

ヒストグラムオブジェクトから特定の値を抽出するには、JSON 操作を使用できます。 例:

mysql> SELECT
         TABLE_NAME, COLUMN_NAME,
         HISTOGRAM->>'$."data-type"' AS 'data-type',
         JSON_LENGTH(HISTOGRAM->>'$."buckets"') AS 'bucket-count'
       FROM INFORMATION_SCHEMA.COLUMN_STATISTICS;
+-----------------+-------------+-----------+--------------+
| TABLE_NAME      | COLUMN_NAME | data-type | bucket-count |
+-----------------+-------------+-----------+--------------+
| country         | Population  | int       |          226 |
| city            | Population  | int       |         1024 |
| countrylanguage | Language    | string    |          457 |
+-----------------+-------------+-----------+--------------+

オプティマイザは、統計が収集されるデータ型のカラムにヒストグラム統計を使用します (該当する場合)。 オプティマイザはヒストグラム統計を適用し、定数値に対するカラム値の比較の選択性 (フィルタリング効果) に基づいて行の見積りを決定します。 これらのフォームの述語は、ヒストグラムの使用に適しています:

col_name = constant
col_name <> constant
col_name != constant
col_name > constant
col_name < constant
col_name >= constant
col_name <= constant
col_name IS NULL
col_name IS NOT NULL
col_name BETWEEN constant AND constant
col_name NOT BETWEEN constant AND constant
col_name IN (constant[, constant] ...)
col_name NOT IN (constant[, constant] ...)

たとえば、次のステートメントにはヒストグラムの使用に適した述語が含まれています:

SELECT * FROM orders WHERE amount BETWEEN 100.0 AND 300.0;
SELECT * FROM tbl WHERE col1 = 15 AND col2 > 100;

定数値と比較するための要件には、ABS()FLOOR() などの定数である関数が含まれます:

SELECT * FROM tbl WHERE col1 < ABS(-34);

ヒストグラム統計は、主にインデックス付けされていないカラムに役立ちます。 ヒストグラム統計が適用可能なカラムにインデックスを追加すると、オプティマイザが行の見積りを行うのにも役立ちます。 トレードオフは次のとおりです:

オプティマイザは、ヒストグラム統計から取得したものよりも範囲オプティマイザ行の見積りを優先します。 オプティマイザが範囲オプティマイザが適用されると判断した場合、ヒストグラム統計は使用されません。

インデックス付けされたカラムの場合、インデックス除算を使用して等価比較のために行の見積りを取得できます (セクション8.2.1.2「range の最適化」 を参照)。 この場合、ヒストグラム統計は必ずしも役に立つとはかぎりません。これは、インデックスの分割によって見積もりが向上するためです。

ヒストグラム統計を使用しても、クエリーの実行が改善されない場合があります (統計が最新でない場合など)。 この場合に該当するかどうかを確認するには、ANALYZE TABLE を使用してヒストグラム統計を再生成し、クエリーを再実行します。

または、ヒストグラム統計を無効にするには、ANALYZE TABLE を使用して削除します。 ヒストグラム統計を無効にする別の方法は、optimizer_switch システム変数の condition_fanout_filter フラグをオフにすることです (ただし、他の最適化も無効になる可能性があります):

SET optimizer_switch='condition_fanout_filter=off';

ヒストグラム統計が使用されている場合、結果の効果は EXPLAIN を使用して確認できます。 カラム col1 に使用可能なインデックスがない次のクエリーについて考えてみます:

SELECT * FROM t1 WHERE col1 < 24;

ヒストグラム統計で、t1 の行の 57% が col1 < 24 述語を満たしていることが示されている場合、インデックスがなくてもフィルタリングが発生し、EXPLAINfiltered カラムに 57.00 が表示されます。