第04章_論理アーキテクチャ

第04章_論理アーキテクチャ

1. 論理アーキテクチャの分析

1.1 サーバーはクライアントのリクエストを処理します

では、サーバー プロセスは、クライアント プロセスから送信されたリクエストに対して何を行って、最終的な処理結果を生成するのでしょうか? ここでのクエリリクエストは
表示例:

ここに画像の説明を挿入します

詳しく見てみましょう:

ここに画像の説明を挿入します

1.2 コネクタ

1.3 レイヤ 1: 接続レイヤ

システム (クライアント) が MySQL サーバーにアクセスする前に、最初に行うことは TCP 接続を確立することです。

3 ウェイ ハンドシェイクによって接続が正常に確立されると、MySQL サーバーは TCP によって送信されたアカウント パスワードに対して ID 認証と権限の取得を実行します。

  • ユーザー名またはパスワードが間違っている場合、「ユーザーのためアクセスが拒否されました」エラーが表示され、クライアント プログラムは実行を終了します。
  • ユーザー名とパスワードの認証が通過すると、そのアカウントと接続が所有する権限が権限テーブルから検索され、その後の権限判定ロジックは
    この時に読み取られた権限に依存します。

TCP 接続がリクエストを受信した後、このクライアントと対話するためのスレッドにそのリクエストを割り当てる必要があります。したがって、後続のプロセスを実行するためのスレッドプールが存在します
各接続はスレッド プールからスレッドを取得するため、スレッドの作成と破棄のオーバーヘッドが排除されます。

1.4 レイヤ 2: サービス レイヤ

  • SQLインターフェース: SQLインターフェース
    • ユーザーの SQL コマンドを受け取り、ユーザーがクエリする必要がある結果を返します。たとえば、SELECT ... FROM は SQL
      インターフェイスを呼び出します。
    • MySQLは、DML (データ操作言語)、DDL (データ定義言語)、ストアド プロシージャ、ビュー、トリガー、カスタム関数などの
      複数の SQL 言語インターフェイスをサポートしています。
  • パーサー: パーサー
    • パーサーで SQL ステートメントの構文分析と意味分析を実行します。SQL ステートメントをデータ構造に分解し、
      この構造を後続のステップに渡します。その後の SQL ステートメントの配信と処理は、この構造に基づいています。分解中にエラーが発生した場合は
      、SQL ステートメントが不当であることを意味します。
    • SQL コマンドがパーサーに渡されると、パーサーによって検証および解析され、その構文ツリーが作成されます。クエリ構文ツリーは
      データ ディクショナリに基づいて強化され、クライアントが SQL コマンドを使用しているかどうかが検証されます。クエリを実行する権限があります。構文ツリーの作成後、MySQL は
      SQl クエリの構文も最適化し、クエリを書き換えます。
  • オプティマイザー: クエリ オプティマイザー
    • SQL ステートメントの構文が解析された後、クエリの前に、クエリ オプティマイザーを使用して SQL ステートメントの実行パスが決定され、実行プランが生成されます。
    • この実行プランは、クエリ (テーブル全体の取得またはインデックスの取得) にどのインデックスを使用する必要があるか、テーブル間の接続の順序は何かを示し、最後にストレージ エンジンによって提供されるメソッドが実行プランの手順に従って呼び出されます。実際にクエリを実行し、クエリ結果がユーザーに返されます。
    • クエリには「select-project-join」戦略が使用されます。例えば:
这个SELECT查询先根据WHERE语句进行选取,而不是将表全部查询出来以后再进行gender过
滤。 这个SELECT查询先根据id和name进行属性投影,而不是将属性全部取出以后再进行过
滤,将这两个查询条件连接起来生成最终查询结果。
Caches & Buffers: 查询缓存组件
MySQL内部维持着一些Cache和Buffer,比如Query Cache用来缓存一条SELECT语句的执行结
果,如果能够在其中找到对应的查询结果,那么就不必再进行查询解析、优化和执行的整个过
程了,直接将结果反馈给客户端。
这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等 。
这个查询缓存可以在不同客户端之间共享。
从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。

1. 5 レイヤ 3: エンジン レイヤ

プラグイン ストレージ エンジン層 (ストレージ エンジン) は、MySQL でのデータの保存と取得を真に担当し、物理サーバー レベルで
維持される基盤となるデータに対して操作を実行します
。サーバーは API を介してストレージ エンジンと通信します。ストレージエンジンが異なれば機能も異なるため、
実際のニーズに応じて選択できます。

MySQL 8.0.25 でデフォルトでサポートされるストレージ エンジンは次のとおりです。

1.6 ストレージ層

すべてのデータ、データベースとテーブルの定義、テーブルの各行の内容、インデックスはファイル システムに保存され、ファイルの形式で保存されます。

そしてストレージ エンジンとの対話を完了します。もちろん、InnoDB などの一部のストレージ エンジンは、ファイル システムを使用しない RAW デバイスの直接管理もサポートしています
が、最新のファイル システムの実装により、これは不要になります。ファイル システムの下では、ローカル ディスクや、
DAS、NAS、SAN などのさまざまなストレージ システムを使用できます。

SELECT id,name FROM student WHERE gender = '女';
小故事:
如果我问你9+8×16-3×2×17的值是多少,你可能会用计算器去算一下,最终结果 35 。如果再问你一遍9+8×16-
3×2×17的值是多少,你还用再傻呵呵的再算一遍吗?我们刚刚已经算过了,直接说答案就好了。

1.7 概要

MySQL アーキテクチャ図は、このセクションの冒頭に示されています。SQL 実行プロセスに慣れやすくするために、次のように簡略化できます。

3 層構造に単純化すると、次のようになります。
1. 接続層: クライアントとサーバーは接続を確立し、クライアントは SQL をサーバーに送信します。
2. SQL層(サービス層):SQL文のクエリ処理を実行しますが、データベースファイルの保存方法とは関係ありません。
3. ストレージ エンジン層: データベース ファイルを処理し、データの保存と読み取りを担当します。

2. SQL実行処理

2.1 MySQLにおけるSQL実行処理

MySQL クエリ プロセス:

1. クエリ キャッシュ: サーバーはクエリ キャッシュ内でこの SQL ステートメントを見つけた場合、結果を直接クライアントに返します。そうでない場合は
、パーサー ステージに入ります。クエリのキャッシュは非効率であることが多いため、
この機能は MySQL8.0 以降廃止されたことに注意してください。

ほとんどの場合、クエリ キャッシュは役に立ちません。なぜでしょうか?

クエリ キャッシュはクエリ結果を事前にキャッシュするので、次回実行することなく結果を直接取得できます。注意すべき点は、

MySQL のクエリ キャッシュはクエリ プランをキャッシュするのではなく、クエリの対応する結果をキャッシュします。これは、クエリ マッチングの堅牢性が大幅に低下し
、同じクエリ操作のみがクエリ キャッシュにヒットすることを意味します。2 つのクエリ リクエスト間の文字の違い (スペース、コメント、
大文字小文字など) があると、キャッシュが失われる原因になります。したがって、MySQL のクエリ キャッシュのヒット率は高くありません。

同時に、クエリ リクエストに特定のシステム関数、ユーザー定義の変数と関数、および一部のシステム テーブル (
mysql、information_schema、および Performance_schema データベース内のテーブルなど) が含まれている場合、リクエストはキャッシュされません。一部のシステム関数を
例に挙げると、同じ関数を 2 回呼び出すと異なる結果が生成されることがあります。たとえば、関数 NOW は
呼び出されるたびに最新の現在時刻を生成します。この関数がクエリ リクエストで呼び出された場合、たとえクエリ 要求されたテキスト情報は同じであるため、異なる時点での 2 つのクエリでも異なる結果が得られるはずです。最初のクエリでキャッシュされている場合、最初のクエリの結果を 2 番目のクエリで直接使用することは間違いです。

また、キャッシュであるため、キャッシュが無効になることがあります。MySQL のキャッシュ システムは、関係する各テーブルを監視します。
テーブルの構造またはデータが変更されている限り、INSERT、UPDATE、DELETE、TRUNCATE TABLE、ALTER
TABLE、DROP TABLE、または DROP DATABASE ステートメントがテーブルで使用されている場合は、All を使用してください。このテーブルのキャッシュされたクエリは無効になり、
キャッシュから削除されます。更新圧力が高いデータベースの場合、クエリ キャッシュのヒット率は非常に低くなります。

2. パーサー: パーサーで SQL ステートメントの構文分析と意味分析を実行します。

アナライザーはまず「字句解析」を行います。入力するのは複数の文字列とスペースで構成される SQL ステートメントであり、MySQL は
その中の文字列が何であるか、またそれが何を表しているかを識別する必要があります。MySQL は、入力された「select」キーワードから、これがクエリ ステートメントであることを認識します
また、文字列「T」を「テーブル名 T」として、文字列「ID」を「列 ID」として認識する必要があります。

SELECT employee_id,last_name FROM employees WHERE employee_id = 101;
接着,要做“语法分析”。根据词法分析的结果,语法分析器(比如:Bison)会根据语法规则,判断你输
入的这个 SQL 语句是否满足 MySQL 语法。
select department_id,job_id,avg(salary) from employees group by department_id;
如果SQL语句正确,则会生成一个这样的语法树:
クエリ オプティマイザーでは、論理クエリ最適化ステージと物理クエリ最適化ステージに分けることができます。
4. アクチュエーター:
これまで、実際のテーブルは実際に読み書きされず、実行プランが生成されただけでした。そこで、執行者の段階に入ります。
select * from test 1 join test 2 using(ID)
where test 1 .name='zhangwei' and test 2 .name='mysql高级课程';
方案 1 :可以先从表 test 1 里面取出 name='zhangwei'的记录的 ID 值,再根据 ID 值关联到表 test 2 ,再判
断 test 2 里面 name的值是否等于 'mysql高级课程'。
方案 2 :可以先从表 test 2 里面取出 name='mysql高级课程' 的记录的 ID 值,再根据 ID 值关联到 test 1 ,
再判断 test 1 里面 name的值是否等于 zhangwei。
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。优化
器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。
如果你还有一些疑问,比如优化器是怎么选择索引的,有没有可能选择错等。后面讲到索引我们再谈。
SQL 字句解析のプロセス手順は次のとおりです。
3. オプティマイザー: オプティマイザーは、完全なテーブルの取得に基づいているか、インデックスの取得に基づいているかなど、SQL ステートメントの実行パスを決定します。

例: 次のステートメントは 2 つのテーブル間の結合を実行します。

実行前にユーザーに権限があるかどうかを判断する必要があります。そうでない場合は、権限エラーが返されます。権限があればSQLを実行する

クエリを実行して結果を返します。MySQL 8.0 より前のバージョンでは、クエリ キャッシュが設定されている場合、クエリ結果はキャッシュされます。

たとえば、テーブル テストで ID フィールドにインデックスがない場合、エグゼキュータの実行プロセスは次のようになります。

この時点で、このステートメントの実行は完了します。インデックスのあるテーブルの場合、実行ロジックは同様です。

MySQL における SQL ステートメントの流れは、SQL ステートメント → クエリ キャッシュ → パーサー → オプティマイザー → エグゼキューターです。

select * from test where id= 1 ;
调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 1 ,如果不是则跳过,如果是则将这行存在结果集中;
调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。

2.2 MySQL 8 における SQL 実行原理

1.プロファイリングがオンになっているかどうかを確認します

profiling=0 は閉じていることを意味します。プロファイリングをオンにする、つまり 1 に設定する必要があります。

2. 同じ SQL クエリを複数回実行する
次に、SQL クエリを実行します (任意の SQL クエリを実行できます)。
3. プロフィールを表示する

現在のセッションによって生成されたすべてのプロファイルを表示します。

mysql> select @@profiling;
mysql> show variables like 'profiling';
mysql> set profiling= 1 ;
mysql> select * from employees;
mysql> show profiles;  # 显示最近的几次查询
4. プロフィールを見る
実行計画を表示し、プログラムの実行ステップを表示します。

もちろん、次のように、指定したクエリ ID をクエリすることもできます。

クエリSQLの実行時間結果は上記と同じです。
さらに、より豊富なコンテンツをクエリすることもできます。
続く:
mysql> show profile;
mysql> show profile for query 7 ;
mysql> show profile cpu,block io for query 6 ;
mysql> show profile cpu,block io for query 7 ;

2.3 MySQL 5.7 における SQL 実行原理

上記の動作をMySQL5.7でテストしたところ、前後2回同じSQL文で実行されるクエリ処理は同じであることが分かりました。キャッシュは使わないのでしょうか
ここでは、クエリ キャッシュ モードを明示的に有効にする必要があります。MySQL5.7では以下のように設定します。

1. 構成ファイルでクエリ キャッシュを有効にする

/etc/my.cnf に新しい行を追加します。

2.mysqlサービスを再起動します。
3. クエリ実行プランを有効にする

サービスが再起動されたため、次の手順を再実行してプロファイリングを有効にする必要があります。

4. ステートメントを 2 回実行します。
5. プロフィールを表示する
query_cache_type= 1
systemctl restart mysqld
mysql> set profiling= 1 ;
mysql> select * from locations;
mysql> select * from locations;
6. プロフィールを見る
実行計画を表示し、プログラムの実行ステップを表示します。
mysql> show profile for query 1 ;
mysql> show profile for query 2 ;
結論は自明です。番号 2 を実行する場合、番号 1 を実行する場合よりも情報が大幅に少なくなります。スクリーンショットから、クエリ ステートメントがキャッシュから直接読み取られることがわかります。
データを取得します。

2.4 SQL 構文の順序

MySQL のバージョンが更新されると、オプティマイザーも常にアップグレードされ、実行シーケンスの違いによって生じるパフォーマンスの消費の違いを分析し
、実行シーケンスを動的に調整します。

要件: 各部門の 20 歳以上の人数をクエリし、20 歳以上の人数が 2 人以上であることを確認し、最も人数が多い部門の情報を表示します。

以下は、頻繁に発生するクエリ シーケンスです。

2.5 OracleにおけるSQL実行処理(理解)

Oracle は共有プールを使用して、SQL ステートメントにキャッシュと実行プランがあるかどうかを判断します。このステップを通じて、
ハード解析とソフト解析のどちらを使用する必要があるかを知ることができます。

まず、Oracle での SQL の実行プロセスを見てみましょう。

上の図からわかるように、SQL ステートメントは Oracle で次の手順を経ています。

1. 文法チェック: SQL のスペルが正しいかどうかをチェックし、正しくない場合、Oracle は構文エラーを報告します。

2. セマンティックチェック: SQL 内のアクセスオブジェクトが存在するかどうかをチェックします。たとえば、SELECT ステートメントを作成するときに、列名が正しく書かれていない場合、システムは
エラーを表示します。構文チェックとセマンティック チェックの機能は、SQL ステートメントにエラーがないことを確認することです。

3. 権限チェック:ユーザーがデータにアクセスする権限を持っているかどうかを確認します。

4. 共有プールのチェック:共有プール (Shared Pool) はメモリ プールであり、その主な機能は SQL ステートメントとステートメントの実行計画をキャッシュすることです
Oracle は、SQL 文の実行計画が共有プールに存在するかどうかを確認して、ソフト解析を実行するかハード解析を実行するかを決定します。では、ソフト解析とハード解析
をどのように理解すればよいのでしょうか?

共有プールでは、Oracle はまず SQL 文に対してハッシュ演算を実行し、
そのハッシュ値に基づいてライブラリ キャッシュ (ライブラリ キャッシュ) を検索します。SQL 文の実行計画がある場合は、それをそのまま実行に使用し、 「executor」リンクに直接入力します。これはソフト解析です。

SQL ステートメントと実行計画が見つからない場合、Oracle は解析用の解析ツリーを作成し、実行計画を生成し、
ハード解析である「オプティマイザ」ステップを開始する必要があります。

5. 优化器:优化器中就是要进行硬解析,也就是决定怎么做,比如创建解析树,生成执行计划。
6. 执行器:当有了解析树和执行计划之后,就知道了 SQL 该怎么被执行,这样就可以在执行器中执
行语句了。

共有プールは、ライブラリ キャッシュ、データ ディクショナリ バッファなどを含む Oracle の用語です。主に SQL ステートメントと実行プランをキャッシュするライブラリ キャッシュ領域についてはすでに説明しました
データ ディクショナリ バッファには、テーブル、ビュー、インデックス、その他のオブジェクトなど、Oracle のオブジェクト定義が格納されます
SQL ステートメントを解析するときに、関連するデータが必要な場合は、データ ディクショナリ バッファから抽出されます。

ライブラリ キャッシュ ステップでは、SQL ステートメントをハード解析する必要があるかどうかを決定します。SQL の実行効率を向上させるには、
ハード解析を避けるように努める必要があります。これは、SQL の実行中に、解析ツリーの作成と実行プランの生成に多くのリソースが消費されるためです。

ハード解析を回避し、可能な限りソフト解析を使用するにはどうすればよいのかと疑問に思われるかもしれません。Oracle では、バインド変数が主要な機能です。バインド変数とは、
SQL ステートメント内で変数を使用し、さまざまな変数値によって SQL の実行結果を変更することです。この利点は、
ソフト解析の可能性が高まることですが、欠点は、生成された実行プランが十分に最適化されていない可能性があるため、バインド変数が必要かどうかは状況によって異なります

たとえば、次のクエリ ステートメントを使用できます。

次のようなバインド変数を使用することもできます。

これら 2 つのクエリ ステートメントの効率は、Oracle ではまったく異なります。player_id = 10001 をクエリしてから、
10002 や 10003 などのデータをクエリすると、各クエリによって新しいクエリ解決が作成されます。2 番目の方法ではバインド変数を使用する
ため、最初のクエリの後、共有プール内にこのタイプのクエリの実行プランが存在します。これはソフト解析です。

したがって、バインド変数を使用することで、ハードな解析を減らし、Oracle の解析ワークロードを軽減できます。ただし、この方法には欠点もあり、
動的SQLを使用する場合、パラメータが異なるとSQLの実行効率が異なり、SQLの最適化が難しくなります。

Oracle のアーキテクチャ図:

SQL> select * from player where player_id = 10001 ;
SQL> select * from player where player_id = :player_id;
簡略図:
まとめ:

Oracle と MySQL では、SQL クエリのソフトウェア実装に違いがあります。
オラクルは、ソフト解析を実行するかハード解析を実行するかを決定するために使用される共有プールの概念を提案しました。

3. データベースバッファプール(バッファプール)

バッファー プールの役割を理解した後は、バッファー プールの別の機能である先読みについても理解する必要があります。
バッファー プールの機能は I/O 効率を向上させることであり、データを読み取るときは「局所性の原則」があり、一部のデータを使用します。
データによると、その周囲のデータが使用される可能性が高いため、「事前読み取り」メカニズムを使用して事前にデータをロードし、将来のディスク I/O 操作の可能性を減らすことができます。
InnoDB存储引擎是以页为单位来管理存储空间的,我们进行的增删改查操作其实本质上都是在访问页
面(包括读页面、写页面、创建新页面等操作)。而磁盘 I/O 需要消耗的时间很多,而在内存中进行操
作,效率则会高很多,为了能让数据表或者索引中的数据随时被我们所用,DBMS 会申请占用内存来作为
数据缓冲池,在真正访问页面之前,需要把在磁盘上的页缓存到内存中的Buffer Pool之后才可以访
问。
这样做的好处是可以让磁盘活动最小化,从而减少与磁盘直接进行 I/O 的时间。要知道,这种策略对提
升 SQL 语句的查询性能来说至关重要。如果索引的数据在缓冲池里,那么访问的成本就会降低很多。

3.1 バッファプールとクエリキャッシュ

バッファプールとクエリキャッシュは同じものですか? いいえ。
1. バッファプール
首先我们需要了解在 InnoDB 存储引擎中,缓冲池都包括了哪些。
在 InnoDB 存储引擎中有一部分数据会放到内存中,缓冲池则占了这部分内存的大部分,它用来存储各种
数据的缓存,如下图所示:
从图中,你能看到 InnoDB 缓冲池包括了数据页、索引页、插入缓冲、锁信息、自适应 Hash 和数据字典
信息等。
缓存池的重要性:
缓存原则:
“位置 * 频次”这个原则,可以帮我们对 I/O 访问效率进行优化。
首先,位置决定效率,提供缓冲池就是为了在内存中可以直接访问数据。
其次,频次决定优先级顺序。因为缓冲池的大小是有限的,比如磁盘有 200 G,但是内存只有 16 G,缓冲
池大小只有 1 G,就无法将所有数据都加载到缓冲池里,这时就涉及到优先级顺序,会优先对使用频次高
的热数据进行加载。
缓冲池的预读特性:
バッファー プールの役割を理解した後は、バッファー プールの別の機能である先読みについても理解する必要があります。
バッファー プールの機能は I/O 効率を向上させることであり、データを読み取るときは「局所性の原則」が存在します。
あるデータを使用した後は、その周囲のデータも使用される可能性が高いため、事前に読み込む「先読み」機構を使用することで、将来のデータを削減できます。
可能なディスク I/O 操作。
2. クエリキャッシュ
では、クエリキャッシュとは何でしょうか?
クエリ キャッシュはクエリ結果を事前にキャッシュするので、次回実行することなく結果を直接取得できます。注意すべき点は、

MySQL のクエリ キャッシュはクエリ プランをキャッシュするのではなく、クエリの対応する結果をキャッシュします。ヒット条件が厳しく、データテーブルが
変更されるとクエリキャッシュが無効になるため、ヒット率が低くなります。

3.2 バッファプールはどのようにデータを読み取るのですか?

バッファー プール マネージャーは、頻繁に使用されるデータを保存するために最善を尽くし、データベースがページを読み取るときに、最初にページを決定します。
バッファプールにあるかどうかに関係なく、存在する場合は直接読み取られ、存在しない場合はメモリまたはディスクを介してバッファプールにページが格納されて処理されます。
行が読み取られます。
データベース内のキャッシュの構造と役割を次の図に示します。
SQL ステートメントの実行時にキャッシュ プール内のデータを更新すると、データはすぐにディスクに同期されますか?

3.3 バッファプールサイズの表示/設定

InnoDB ストレージ エンジンを使用している場合は、 innodb_buffer_pool_size 変数を調べることでバッファ プール サイズを確認できます
コマンドは次のとおりです。

この時点の InnoDB のバッファ プール サイズは、134217728 / 1024 / 1024 = 128 MB しかないことがわかります。次のように、バッファ プール サイズを、たとえば
256 MB に変更できます。

show variables like 'innodb_buffer_pool_size';
set global innodb_buffer_pool_size = 268435456 ;
または:
次に、変更されたバッファー プール サイズを確認します。256 MB に正常に変更されました。

3.4 複数のバッファプールインスタンス

これは、2 つのバッファー プール インスタンスを作成することを示しています。

次のコマンドを使用して、バッファー プールの数を確認する方法を見てみましょう。

では、各バッファー プール インスタンスは実際にどれくらいのメモリ領域を占有するのでしょうか? 実際には、次の式を使用して計算されます。

つまり、合計サイズをインスタンスの数で割った結果が、各バッファー プール インスタンスが占めるサイズになります。

3.5 拡張された質問

バッファ プールは MySQL メモリ構造の非常に中心的なコンポーネントであり、最初はブラック ボックスとして想像できます。

ブラックボックス下でのデータ更新プロセス

[server]
innodb_buffer_pool_size = 268435456
[server]
innodb_buffer_pool_instances = 2
show variables like 'innodb_buffer_pool_instances';
innodb_buffer_pool_size/innodb_buffer_pool_instances
アップデート中に突然エラーが発生したので、アップデート前のバージョンに戻したいのですが、どうすればよいですか?データの永続性とトランザクションの回復の保証
クラッシュリカバリーすらできないのに、どうやってそれについて語ることができるでしょうか?

答え: Redo ログと Undo ログ

おすすめ

転載: blog.csdn.net/github_36665118/article/details/134139170