記事ディレクトリ
1. MySQL インフラストラクチャ
簡単に言うと、MySQL は主にサーバー層とストレージ エンジン層に分かれています。
- サーバー層: 主にコネクタ、クエリ キャッシュ、アナライザー、オプティマイザー、エグゼキュータなどが含まれます。ストアド プロシージャ、トリガー、ビュー、関数など、すべてのクロスストレージ エンジン機能はこの層で実装され、一般的なログモジュール binlog ログモジュール。
- ストレージ エンジン: 主にデータの保存と読み取りを担当します。交換可能なプラグイン アーキテクチャを採用し、InnoDB、MyISAM、Memory などの複数のストレージ エンジンをサポートします。InnoDB エンジンには独自のログ モジュール redolog モジュールがあります。最も一般的に使用されるストレージ エンジンは InnoDB で、MySQL 5.5 以降、デフォルトのストレージ エンジンとして使用されています。
1. サーバー層の基本コンポーネントの紹介
-
コネクタ: これは、高レベルのガードと同様に、主にID 認証と権限に関連する機能に関連します。
主に、データベースへのユーザー ログイン、アカウント パスワードの検証を含むユーザー認証、権限、その他の操作を担当します。ユーザー アカウントのパスワードが渡された場合、コネクタは権限テーブル内のユーザーのすべての権限を照会し、次に権限を照会します。このとき論理的な判断は、このときに読み取られた権限データに依存します。つまり、後で接続が切断されない限り、管理者がユーザーの権限を変更しても、ユーザーは影響を受けません。
-
クエリ キャッシュ: 主に、実行する SELECT ステートメントとステートメントの結果セットをキャッシュするために使用されます。
キャッシュキーがヒットした場合は直接クライアントに返されますが、ヒットしなかった場合は次の操作が実行され、完了後に結果が次回の呼び出しの便宜のためにキャッシュされます。もちろん、キャッシュ クエリが実際に実行されるときも、テーブルに対するクエリ条件があるかどうかを確認するためにユーザーの権限がチェックされます。実際のビジネス シナリオではクエリ キャッシュの無効化が非常に頻繁に発生する可能性があるため、MySQL クエリにキャッシュを使用することは推奨されません。テーブルを更新すると、このテーブル上のすべてのクエリ キャッシュがクリアされます。頻繁に更新されないデータの場合は、キャッシュを使用することができます。MySQL 8.0 以降、キャッシュ機能は削除されました。
-
アナライザー: MySQL がキャッシュにヒットしない場合は、アナライザーに入ります。アナライザーは主に SQL ステートメントの目的を分析するために使用されます。アナライザーはいくつかのステップにも分かれています:
- 字句解析: SQL ステートメントは複数の文字列で構成されており、まず、select、クエリ対象のテーブル、フィールド名、クエリ条件などのキーワードを抽出する必要があります。
- 文法解析:主に入力したSQLが正しいか、MySQLの構文に準拠しているかを判断します。
-
オプティマイザー: オプティマイザーの役割は、複数のインデックスがある場合のインデックスの選択方法、複数のテーブルをクエリする場合の関連付け順序の選択方法など、オプティマイザーが考える最適な実行計画 (最適でない場合もあります) を実行することです。 。オプティマイザを通過した後、このステートメントの具体的な実行が決定されたと言えます。
-
Executor: 実行プランを選択すると、MySQL は実行を開始する準備が整います。まず、実行前にユーザーに権限があるかどうかを確認します。権限がない場合は、エラー メッセージが返されます。権限がある場合は、エンジンのインターフェイス。インターフェイスの実行結果を返します。
2. ステートメントの実行
1) クエリ文
-
ステートメントに権限があるかどうかをクエリします。権限がない場合は、直接エラー メッセージが返されます。権限がある場合は、まずバージョン 8.0 より前のキャッシュをクエリし、SQL ステートメントをキーとして使用して、権限があるかどうかをクエリします。結果がメモリに保存されます。存在する場合は、直接返されます。いいえ、次のステップに進みます。
-
アナライザーを介して字句解析を実行して、SQL ステートメントの主要な要素を抽出します。たとえば、上記のステートメントはクエリ選択として抽出され、クエリ対象のテーブルの名前は tb_student で、すべての列をクエリする必要があります。クエリ条件はこのテーブルの id='1' です。次に、SQL文に文法上の誤りがないか、キーワードが正しいかなどを判断します。チェックに問題がなければ次のステップに進みます。
-
次のステップでは、オプティマイザが実行計画を決定します。SQL ステートメントには、次のような複数の実行計画が含まれる場合があります。
a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。 b.先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。
次に、オプティマイザは、独自の最適化アルゴリズムに従って、最高の実行効率を持つソリューションを選択します (オプティマイザは、それが必ずしも最高であるとは限らないと考えます)。そして、実行計画を確認したら、実行を開始する準備が整います。
-
権限検証を行い、権限がなければエラーメッセージを返し、権限があればデータベースエンジンインターフェースを呼び出し、エンジンの実行結果を返します。
2) ステートメントを更新する
- まず更新するデータをクエリします。キャッシュがある場合はキャッシュも使用します。キャッシュがない場合はストレージ エンジンを通じて検索します。バッファ プールに記録されている場合は直接返します。そうでない場合は、ディスクに書き込まれて読み取られます。
- 実行プログラムは、クエリされたデータを更新し、ストレージ エンジン インターフェイスを呼び出してこのデータを書き込みます。InnoDB エンジンは、まずそれを UNDO ログに記録し、次にデータをメモリに保存し、同時に REDO ログを記録します。この時点で、REDO ログのステータスは準備中ですが、実行が完了し、いつでも送信できることを実行者に伝えます。
- エグゼキューターは、バイナリログを受信した後、バイナリログを更新し、エンジンインターフェイスを呼び出して、REDO ログステータスをコミットステータスに変更します。
- アップデートが完了しました
データベースのクラッシュから回復するには:
REDO ログ内のトランザクションが完了している場合、つまりコミット フラグが再び付いている場合は、トランザクションを直接送信します。
REDO ログ内のトランザクションが準備状態の場合、バイナリログで該当するトランザクションが完了しているかどうかを判断します
完了した場合はトランザクションを直接コミットします
それ以外の場合は、元に戻すログを使用してロールバックします。
バイナリ ログにはレコードがないため、スレーブ ライブラリは同期中にこの操作を実行できません。メイン ライブラリがロールバックせずに実行を継続すると、マスターとスレーブの不整合が発生します。同様に、バイナリ ログが完了した場合でも、 REDO ログのステータスがコミットでない場合は、送信する必要があります。
詳細については、「MySQL トランザクションの詳細と分離レベルの実装」の記事を参照してください。
2、MySQL ストレージ エンジン
MySQL は複数のストレージ エンジンをサポートしています。show Engine コマンドを使用して、MySQL でサポートされているすべてのストレージ エンジンを表示できます。
MySQL 5.5.5 より前は、MyISAM が MySQL のデフォルトのストレージ エンジンでした。バージョン 5.5.5 以降、InnoDB が MySQL のデフォルトのストレージ エンジンになります
MySQL ストレージ エンジンはプラグイン アーキテクチャを採用しており、複数のストレージ エンジンをサポートしており、さまざまなシナリオのニーズを満たすために、さまざまなデータベース テーブルに異なるストレージ エンジンを設定することもできます。ストレージ エンジンはデータベース ベースではなくテーブル ベースです。
InnoDB と MyISAM の比較:
-
トランザクション: MyISAM はトランザクションをサポートしませんが、InnoDB はトランザクションをサポートします。InnoDB の場合、各ステートメントはトランザクションにカプセル化され、デフォルトで自動的にコミットされます。
-
ロック: MyISAM にはテーブル レベルのロックのみがあります。InnoDB は行レベルのロックとテーブル レベルのロックをサポートします。デフォルトは行レベルのロックです。
-
外部キー: MyISAM は外部キーをサポートしませんが、InnoDB は外部キーをサポートします (外部キーを含む InnoDB テーブルは MyISAM への変換に失敗します)
外部キーはデータの一貫性を維持するのに役立ちますが、パフォーマンスがある程度低下します。通常、外部キーは使用されず、コード内で制約されます。
-
インデックス: MyISAM と InnoDB は両方ともインデックス構造として B+ ツリーを使用しますが、MyISAM は非クラスター化インデックス (インデックスとデータ分離) ですが、InnoDB の主キー インデックスはクラスター化インデックスです。
-
安全性: MyISAM はデータベースクラッシュ後の安全なリカバリをサポートしていませんが、InnoDB はサポートしています (REDO ログに応じて)
-
MVCC: MyISAM はサポートしていませんが、InnoDB はサポートしています。MyISAM は行レベルのロックすらサポートしておらず、MVCC は行レベルのロックのアップグレードであるため、当然のことながら行レベルのロックをサポートしていません。
-
count: MyISAM はディスク上のデータ行の総数を保存します。これは、行の総数をクエリするときに直接返すことができますが、InnoDB データ テーブルの行数を事前に決定することはできません (InnoDB のトランザクション特性のため、同じタイム テーブル内の行数はトランザクションごとに異なります (言語が異なります)。そのため、クエリを実行するときに現在のトランザクションに従ってのみ決定でき、行数は count を呼び出すときに再計算する必要があります。
- count(*):最も短い key_len を使用してセカンダリ インデックスを走査します。そうでない場合は、クラスター化インデックスに従って走査します** (クラスター化インデックスの値は読み取られません)**
- count(1):クラスター化インデックスを走査します** (クラスター化インデックスの値を読み取りません)**
- count (インデックス フィールド): クラスター化インデックスを走査します **(インデックスの値を読み取ります。null はカウントしません)**
- count (非インデックスフィールド): フルテーブルスキャン
-
フルテキスト インデックス: MyISAM はフルテキスト インデックスをサポートしており、クエリ速度が高速です。InnoDB5.7 より前では、フルテキスト インデックスはサポートされていませんでした。
-
主キー: MyISAM にはそれがない可能性がありますが、InnoDB にはそれが必要です。指定しない場合、システムは等しくない要素を含む列を検索し、この列を使用して B+ ツリーを編成します。列が存在しない場合は、保持するために非表示の列 row_id を作成します。
3. InnoDB のストレージ構造
InnoDB の論理ストレージ構造の観点から見ると、すべてのデータはテーブルスペースと呼ばれるスペースに論理的に保存されます。**表スペースはセグメント、エクステント、ページで構成されます**。
InnoDB ストレージ エンジンを使用してテーブルを作成すると、対応するテーブル スペースであるテーブル name.ibd ファイルがディスク上に作成されます。
テーブルには、インデックス セグメント、データ セグメント、ロールバック セグメントなどが含まれます。このうち、インデックスセグメントは非リーフノード部分、データセグメントはリーフノード部分であり、ロールバックセグメントはデータのロールバックとマルチバージョン制御に使用される。
1セグメントには256のエリアが含まれ、1エリアは64データページに対応し、1データページはデフォルトで16K、1データエリアは1MBです。
4、SQL実行計画
実行プランとは、MySQL クエリ オプティマイザーによって最適化された後の SQL ステートメントの特定の実行方法を指します。
実行プランは通常、SQL パフォーマンス分析や最適化などのシナリオで使用されます。EXPLAIN
の結果を通じて、データ テーブルのクエリ順序、データ クエリ操作の操作タイプ、ヒットできるインデックス、実際にヒットするインデックス、各データ テーブルの行数などの情報を知ることができます。尋ねられた。
EXPLAIN
このステートメントは、関連するステートメントを実際に実行するのではなく、クエリ オプティマイザーを通じてステートメントを分析し、最適なクエリ プランを見つけて、対応する情報を表示します。
実行結果には次のように合計 12 列があります。
-
id: SQL ステートメントには複数の SELECT が含まれる場合があり、id はクエリ全体の SELECT ステートメントのシーケンスを識別するために使用されます。IDが同じ場合は上から順に実行されます、IDが異なる場合はIDが大きい方の優先順位が高くなります、他の行の結合結果を参照する場合、この値はNULLでも構いません
-
select_type: クエリのタイプ。主に、通常のクエリ、結合クエリ、サブクエリなどの複雑なクエリを区別するために使用されます。
- SIMPLE: 単純なクエリ。UNION やサブクエリは含まれません。
- PRIMARY: クエリにサブクエリまたは他の部分が含まれている場合、外側の SELECT は PRIMARY としてマークされます。、
- SUBQUERY: サブクエリの最初の SELECT
- UNION: UNION ステートメントで、UNION の後に現れる SELECT
- DERIVED: FROM に出現するサブクエリは DERIVED としてマークされます。
- UNION RESULT: UNION クエリの結果
-
table: クエリで使用されるテーブルの名前。各行には対応するテーブル名があります。テーブル名は、通常のテーブルに加えて、以下にリストされている値である場合もあります。
<unionM,N>
: この行は、ID が M と N の行の UNION 結果を参照します。<derivedN>
: この行は、ID が N のテーブルによって生成された派生テーブルの結果を参照します。派生テーブルは、FROM ステートメントのサブクエリから生成される場合があります。<subqueryN>
: この行は、ID N のテーブルによって生成された実体化されたサブクエリの結果を参照します。
-
パーティション: 一致するパーティション、またはパーティション化されていないテーブルの場合は NULL
-
type: クエリ実行のタイプ。クエリがどのように実行されるかを示します。すべての値の最良から最悪の順序は次のとおりです: system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
- system: テーブルで使用されるエンジンがテーブルの行統計に対して正確であり (MyISAM など)、テーブル内にレコードが 1 行しかない場合、アクセス方法は system であり、これは const の特殊なケースです。
- const: テーブル内に一致するレコードは最大 1 行あり、1 つのクエリで見つけることができます。主キーまたは一意のインデックスのすべてのフィールドをクエリ条件として使用する場合によく使用されます。
- eq_ref: リンク テーブルをクエリする場合、現在のテーブルには前のテーブルの行に対応する行が 1 つだけあります。system と const を除く最適な結合方法で、主キーまたは一意のインデックスのすべてのフィールドを結合条件として使用する場合によく使用されます。
- 参照: 通常のインデックスをクエリ条件として使用すると、クエリ結果で複数の適格な行が見つかる可能性があります。
- Index_merge: クエリ条件で複数のインデックスが使用されている場合、インデックス マージの最適化がオンになっていることを意味します。このとき、実行プランのキー列には使用されたインデックスがリストされます。
- range: インデックス列に対して範囲クエリを実行します。実行プランのキー列は、どのインデックスが使用されるかを示します。
- インデックス: クエリは ALL と同様にインデックス ツリー全体を走査しますが、インデックスがスキャンされる点が異なり、インデックスは通常メモリ内にあるため高速です。
- ALL: フルテーブルスキャン
-
possible_keys: MySQL がクエリを実行するときに使用する可能性のあるインデックスを示します。この列が NULL の場合は、使用できるインデックスがないことを意味します。この場合、WHERE ステートメントで使用されている列をチェックして、これらの列の 1 つ以上にインデックスを追加できるかどうかを確認する必要があります。 。
-
key: MySQL が実際に使用するインデックスを示します。NULL の場合、インデックスは使用されません。
-
key_len: このカラムは、MySQL が実際に使用するインデックスの最大長を示します。ジョイント インデックスが使用されている場合は、複数のカラムの長さの合計になる場合があります。需要に応えることを前提にすれば、短いほど良いのです。key 列に NULL が表示される場合、key_len 列にも NULL が表示されます。
-
ref: インデックス同等クエリを使用する場合にインデックスと比較する列または定数
-
rows: テーブルの統計と選択に基づいて、検索または読み取る行数を大まかに見積もることを示します。値が小さいほど良好です。
-
filtered: テーブル条件でフィルタリングした後、保持されたレコードの割合
-
追加: MySQL のクエリ解析に関する追加情報が含まれており、この情報を通じて、MySQL がクエリを実行する方法をより正確に理解できます。一般的な値は次のとおりです。
-
ファイルソートの使用: ソートには外部インデックス ソートが使用され、ソートには内部インデックスは使用されません。
-
一時的な使用: MySQL は、ORDER BY と GROUP BY で一般的な、クエリの結果を保存するための一時テーブルを作成する必要があります。
-
インデックスを使用する: クエリがテーブルに戻らずにカバー インデックスを使用することを示し、クエリ効率が非常に高くなります。
-
インデックス条件の使用: クエリ オプティマイザーがインデックス条件プッシュダウンの機能を使用することを選択することを示します。
-
where を使用: クエリが条件付きフィルター処理に WHERE 句を使用することを示します。通常、インデックスが使用されていない場合に発生します。
-
結合バッファの使用 (ブロック ネスト ループ): テーブルを接続する方法。つまり、駆動テーブルがインデックスを使用しない場合、MySQL は最初に駆動テーブルを読み取って結合バッファに置き、次に駆動テーブルを走査し、運転台についてはお問い合わせください。
Extra 列に「Using filesort」または「Usingtemporary」が含まれている場合、MySQL のパフォーマンスに問題が発生する可能性があるため、可能な限り回避する必要があります。
-
参考記事:
InnoDB ストレージ エンジンの MVCC 実装 | JavaGuide (Java インタビュー + 学習ガイド)