MySQL クエリの最適化には、解析、前処理、最適化という 3 つのステップが必要です。これらのプロセスのいずれかの過程でエラーが発生する可能性があります。この記事では、エラー処理について詳しく説明しません。ただし、MySQL がクエリを実行する方法を理解して、より優れたクエリを作成できるようにするのに役立ちます。 パーサーとプリプロセッサ最初に、MySQL のパーサーはクエリを一連の命令に分割し、それらから「解析ツリー」を構築します。パーサーは、MySQL の SQL 構文を使用してクエリ ステートメントを変換および検証します。たとえば、パーサーはクエリ内の命令が有効で正しい順序であることを確認し、文字列内の引用符が一致しないなどのエラーをチェックします。 プリプロセッサは、構築された解析ツリーをチェックして、パーサーが処理できない意味情報がないかどうかを確認します。たとえば、テーブルと列の存在がチェックされ、フィールド名とエイリアスが処理されて、列参照が明確であることが保証されます。次に、プリプロセッサが権限をチェックします。これは通常、かなり高速です (サーバーに多数の権限が設定されていない場合)。 クエリオプティマイザーパーサーとプリプロセッサを通過した後、解析ツリーは有効であると判断され、オプティマイザーによって処理され、最終的にクエリ プランに変換されます。多くの場合、同じ結果を生成するクエリを実行する方法は多数あり、オプティマイザーの役割は最適なオプションを見つけることです。 MySQL はコスト見積もりに基づくオプティマイザーを使用します。つまり、複数の実行プランのコストを予測し、コストが最も低いものを選択します。元の単位コストはランダムな 4KB データ ページの読み取りでしたが、現在はより複雑になり、WHERE 比較条件を実行するコストも含まれるようになりました。 Last_query_cost セッション変数を表示することで、クエリ オプティマイザーによるクエリ ステートメントのコストの見積もりを表示できます。 sakila.film_actor から SQL_NO_CACHE COUNT(*) を選択します。 'Last_query_cost' のようなステータスを表示します。 表示される Last_query_cost は、クエリを完了するために、対応する数のランダム データ ページ アクセスを実行する必要があることをオプティマイザーが見積もっていることを意味します。これは以下の統計的推定に基づいています。
オプティマイザーはキャッシュの推定を考慮せず、結果が毎回ディスク I/O から読み取られると想定します。オプティマイザーは、次の理由により、必ずしも最適な実行プランを選択するとは限りません。
MySQL クエリ オプティマイザーは、多くの最適化方法を使用してクエリ ステートメントをクエリ実行プランに変換する非常に複雑な部分です。通常、最適化には静的最適化と動的最適化の 2 種類があります。静的最適化は、解析ツリーを検査するだけで実行できます。たとえば、オプティマイザーは数学的な演算ルールを通じて WHERE 条件を方程式に変換できます。静的最適化は、WHERE 条件内の定数値などの特定の値とは関係ありません。これらは一度実行され、異なる値でクエリが再度実行された場合でも有効なままです。これは「コンパイル時の最適化」として理解できます。 対照的に、動的最適化はコンテキストに固有であり、さまざまな要因に依存します。たとえば、WHERE 条件の値や、インデックス内の対応するデータ行の数などです。このプロセスはクエリごとに再推定する必要があり、「実行時の最適化」として理解できます。 MySQL の一般的な最適化方法を以下に示します。
EXPLAIN SELECT film.film_id、film_actor.actor_id sakila.filmより INNER JOIN sakila.film_actor USING(film_id) ここで、film.film_id = 1; MySQL はこのクエリを 2 つのステップに分割するため、分析結果には 2 つの行が含まれます。最初のステップは、フィルム テーブル内の対応するデータ行を見つけることです。クエリは主キー film_id に基づいているため、MySQL はデータが 1 行しかないことを認識します。 したがって、このときのクエリ解析結果のrefは定数となります。 2 番目のステップでは、MySQL は film_id を既知の値として扱うため、film_actor のクエリの ref も定数になります。その他の同様のシナリオとしては、WHERE、USING、または ON 条件の制約が等式である場合が挙げられます。この例では、MySQL は USING 条件の film_id がすべてのクエリで同じ値であり、この値は WHERE 条件の film_id と同じでなければならないことを認識しています。
EXPLAIN SELECT film.film_id FROM sakila.film WHERE film_id=1; 分析結果の「追加」フィールドに、「const テーブルを読み取った後に不可能な WHERE が検出されました」と表示されます。早期終了が発生する可能性があるその他の状況としては、次のようなものがあります。 フィルム.フィルムIDを選択 sakila.filmより 左外部結合 sakila.film_actor USING (film_id) sakila.film_actor.film_id が NULL の場合; このクエリでは、俳優が出演している映画は除外されます。各映画には複数の俳優が登場する場合がありますが、俳優が見つかると、MySQL は現在の映画の処理を停止し、次の映画に進みます。 DISTINCT と NOT EXISTS でも同様の状況が発生します。
フィルム.フィルムIDを選択 sakila.filmより INNER JOIN sakila.film_actor USING(film_id) ここで、film.film_id > 500; MySQL は、WHERE 制約が film テーブルだけでなく film_actor テーブルにも適用されることを認識します。ただし、この最適化効果は他のデータベースでは達成されない可能性があります。
実際、MySQL では上記に挙げたもの以外にも多くの最適化方法が使用されており、ここですべてを列挙することは不可能です。 MySQL のオプティマイザーの複雑さと、それがどれほどスマートであるかを思い出してください。したがって、MySQL オプティマイザに改善の余地がなくなるまでクエリ ステートメントを無期限に最適化するのではなく、オプティマイザがその役割を果たせるようにする必要があります。もちろん、MySQL のオプティマイザーは非常にスマートですが、必ずしも最良の結果が得られるとは限りません。最良の結果がわかっていても、MySQL がそれを知らない場合もあります。この場合、クエリ ステートメントを最適化して MySQL が最適化作業を完了できるようにすることができますが、クエリ ヒントを追加したり、クエリを書き直したり、データ テーブルの設計を変更したり、インデックスを追加したりする必要がある場合もあります。 上記は、MySQL クエリ最適化プロセスを理解するための詳細です。MySQL クエリ最適化の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
この記事では、カルーセルチャートの小さなケースを実装するためのJSの具体的なコードを参考までに共有し...
目次概要1. URL経由でダウンロード2. aタグのダウンロード属性とblobコンストラクタを組み合...
導入前回の記事では、Redis をインストールして設定しましたが、まだ終わりではありません。PHP ...
1. はじめにDocker には、タスクを構成する複数の Docker コンテナをオーケストレーショ...
Linux サーバーに GRUB をインストールする方法クラウド移行ツールを使用して、CentOS ...
カリで再現まず、必要なvim.basicファイルにsuid権限を設定します。 chmod u+s /...
この記事では主にDockerを使ってElasticSearch:バージョン6.8.4をデプロイする方...
幅と高さを直接使用することはできません。 display:block; または display:in...
この記事では、入力ボックスコンポーネントを手動で実装するための具体的なコードを参考までに紹介します。...
1. 命名規則1. データベース名、テーブル名、フィールド名には小文字を使用し、アンダースコアで区切...
ユーザー名前空間は Linux 3.8 で追加された新しい名前空間で、ユーザー ID やグループ I...
土曜日、本番サーバー上の Redis サーバーが利用できなくなり、エラー メッセージは次のようになり...
2次元配列の次元削減配列インスタンスメソッド concat と ES6 スプレッド演算子を使用した次...
<br />テキストデザインでは、通常、テキストのレイアウト、つまりテキストをより美しく...
皆様の参考と操作を容易にするために、様々な主要ウェブサイトを検索し、関連するスケジュールされたタスク...