MySQL 8.0 リファレンスマニュアル


8.9.1 クエリー計画評価の制御

クエリーオプティマイザのタスクは SQL クエリーを実行するために最適なプランを見つけることです。 良いプランと悪いプランのパフォーマンスの差は、桁違い (つまり、数秒に対して数時間や数日にまで) になる可能性があるため、MySQL のオプティマイザを含むほとんどのクエリーオプティマイザは、多かれ少なかれ、すべての可能なクエリー評価プランの中から最適なプランを徹底的に探します。 結合クエリーに対して、MySQL オプティマイザによって調査される可能なプランの数は、クエリーで参照されるテーブル数とともに指数関数的に増大します。 少数のテーブル (一般に 7 から 10 未満) の場合、これは問題になりません。 ただし、大きいクエリーが発行されると、クエリーの最適化に費やされる時間がサーバーのパフォーマンスの大きなボトルネックになる可能性があります。

クエリー最適化のより柔軟な方法により、ユーザーはオプティマイザが最適なクエリー評価プランをどの程度徹底的に探すかを制御できます。 一般的な考えは、オプティマイザによって調査されるプランが少ないほど、クエリーのコンパイルに費やす時間も少なくなるということです。 一方、オプティマイザは一部のプランをスキップするため、最適なプランを見逃す可能性もあります。

評価するプランの数に関して、オプティマイザの動作を 2 つのシステム変数を使用して制御できます。

  • optimizer_prune_level 変数は、オプティマイザに、テーブルごとにアクセスされる行数の見積もりに基づいて、特定のプランをスキップするように伝えます。 経験上、この種類の学習による推測は最適なプランをめったに見逃すことはなく、クエリーのコンパイル時間を劇的に短縮できます。 デフォルトでこのオプションがオン optimizer_prune_level=1 であるのはこのためです。 ただし、オプティマイザがより適したクエリー計画を見逃したと思う場合は、クエリーのコンパイルにかなりの時間がかかるリスクを伴いますが、このオプションをオフにする (optimizer_prune_level=0) ことができます。 この経験則を使用しても、オプティマイザはまだ指数関数的な数のプランを探索します。

  • optimizer_search_depth 変数は、オプティマイザがそれ以上拡張すべきかどうかを評価するために、不完全な各プランの将来をどの程度見通すかを伝えます。 optimizer_search_depth の値を小さくするほど、クエリーのコンパイル時間が桁違いに少なくなる可能性があります。 たとえば、12、13、またはそれ以上のテーブルのクエリーは、optimizer_search_depth がクエリー内のテーブル数に近い場合、コンパイルに数時間または数日間も容易に必要になることがあります。 同時に、3 か 4 に等しい optimizer_search_depth でコンパイルされた場合、オプティマイザは同じクエリーで 1 分以内にコンパイルできることがあります。 optimizer_search_depth の適切な値が不明な場合、この変数を 0 に設定することで、オプティマイザに自動的に値を決定させることができます。


関連キーワード:  クエリー, テーブル, インデックス, InnoDB, プラン, オプティマイザ, 評価, 制御, 計画, 結合