MySQLのバッファプールの詳細な説明

MySQLのバッファプールの詳細な説明

MySQL のデータはディスクに書き込む必要があることは誰もが知っています。ディスクの読み取りと書き込みは、特にメモリと比較すると非常に遅くなります。ただし、通常 SQL を実行すると、書き込み操作と読み取り操作の両方で、予想ほど遅くなく、すぐに結果を得ることができます。

インデックスがあるから、当然インデックスがあった方が速いと言うかもしれません。しかし、インデックス ファイルもディスクに保存されるため、検索プロセスによってディスク I/O が生成されます。データ行に対して複数の操作を同時に実行すると、ディスク IO が何度も繰り返されるのではないでしょうか。

おそらくあなたも考えたことがあるでしょうが、データをメモリに保存するだけではだめなのでしょうか?メモリがディスクよりも高速であることは間違いありません。そうです、それではどうやって保存するのでしょうか? これが今日お話しするトピック、つまりバッファ プールです。

読者の皆様、ぜひフォローしてくださいね〜

図:マインドマップ

バッファプールを使い始める

上で述べたように、行を操作する SQL を実行する場合、必ずしもディスク操作を直接実行できるとは限りません。少なくとも緩衝地帯はある。そうでなければ、毎回巣の奥深くまで行くのに誰が耐えられるだろうか。

ここでバッファ プールが登場します。簡単に言えば、メモリ領域です。その存在理由の 1 つは、毎回ディスクにアクセスすることを回避し、最も頻繁にアクセスされるデータをキャッシュに入れて、データのアクセス速度を向上させることです。

バッファプールの機能がわかったところで、バッファプールが MySQL アーキテクチャ全体の中でどのような位置を占めているかを見て、マクロ的に理解してみましょう。

内部コンポーネントを見てみましょう。バッファ プールには、データ ページとインデックス ページ以外にもいくつかの種類があります。

バッファプールの応用

バッファ プールについて理解できたので、SQL 実行におけるバッファ プールの役割について最も関心があるかもしれません。前回の記事では、SQL ステートメントの実行プロセスについて簡単に説明しましたが、バッファ プールに関連する問題については触れませんでした。この問題では、エントリ ポイントとして SQL を引き続き使用します。

SQL 文を実行すると、それが読み取り操作である場合、検索対象のデータが配置されているデータ ページがメモリ内にある場合に結果が返されます。それ以外の場合は、対応するデータ ページがメモリにロードされ、結果が返されます。

書き込み操作にも同じことが当てはまります。変更する行が配置されているデータ ページがメモリ内にある場合は、変更後に対応する結果が返されます (もちろん、後続の操作もあります)。存在しない場合は、行に対応するデータ ページがディスクからメモリに読み込まれ、変更されます。

さて、最初の質問に戻りましょう。ディスク操作は遅いのに、SQL 実行は遅くないのはなぜですか?おそらくあなたはもうそれを知っていると思います。

バッファ プールの存在により、ディスク I/O によって発生するオーバーヘッドが大幅に削減されます。操作対象となるデータ行が配置されているデータ ページがキャッシュ内に存在する場合は、ディスクから読み取る必要はありません。この方法では、実行後にすぐに結果を得ることができます。

バッファプールの事前読み取りメカニズム

ディスク I/O がなくなるか減少する限り、実行速度は自然に速くなることがわかります。では、データ ページのロードに伴う避けられないディスク I/O に対処するためのより良い方法はあるのでしょうか?避けられないのであれば、ディスク I/O の数を減らすことが常に選択肢になるのではないでしょうか?

これから説明するのは、MySQL の「先読み」という新機能です。これは、バッファ プールで複数のデータ ページを事前に読み取ることで、Innodb が I/O を最適化する方法です。ディスクの読み取りと書き込みはページ単位で行われるため(固定サイズのデータ​​として理解できます。たとえば、1 ページのデータは 16K です)、毎回少なくとも 1 ページのデータが読み取られます。次に読み取るデータがページ内にある場合は、ディスクから再度読み取る必要がないため、ディスク I/O が削減されます。

対応するページ サイズは、コマンド ラインで次のコマンドを実行すると確認できます。

バッファプールスペース管理

バッファ プールが流行っているのだから、すべてのデータをバッファ プールに入れたらどうかと思うかもしれません。この速度は本当に素晴らしいのですが、それをディスクに保存するのは、年老いた牛が荷車を引くのと同じくらい遅いです。

おい、兄弟、目を覚ませ。メモリの揮発性はさておき、バッファ プールにもサイズ制限がある。すると、また混乱してしまうかもしれません。バッファプールにはサイズ制限があるので、毎回読み取るデータページをどのように管理すればよいのでしょうか。他のデータ ページがスペースを占有しているので、私のスペースはどこにあるのでしょうか?

ここでは、バッファ プールのスペース管理について説明します。実際、バッファ プールの管理の重要な部分は、プール内のデータをどのように整理し、特定の戦略に従ってプール内のデータを削除して、プール内のデータが「オーバーフロー」しないようにしながら、よく使用されるデータがプール内に残るようにすることです。

従来のLRU除去法

バッファ プールは、従来の LRU 方式に基づいてキャッシュ ページを管理します。まず、LRU を使用してどのように管理されるかを見てみましょう。

LRU の正式名称は Least Recently Used で、中国語名は「least Recently Used」です。名前からすぐに分かります。

ここでは 2 つの状況があります。

(1)キャッシュページはすでにバッファプール内にある

この場合、対応するキャッシュ ページは、ディスクから読み取ったり、他のキャッシュ ページを削除したりすることなく、LRU リンク リストの先頭に配置されます。

下の図に示すように、アクセスするデータがページ 6 にある場合は、リンク リストの先頭にページ 6 を配置するだけです。この場合、キャッシュ ページは削除されません。

(2)キャッシュページがバッファプールに存在しない

キャッシュ ページはバッファ内にありません。このとき、対応するデータ ページをディスクから読み取り、リンク リストの先頭に配置し、末尾のキャッシュ ページを削除する必要があります。

下の図に示すように、アクセスするデータがページ 60 にあり、ページ 60 がバッファ プールにない場合は、それがロードされてリンク リストの先頭に配置され、末尾のキャッシュ ページ 17 は削除されます。

バッファプール内のキャッシュページを削除する方法はシンプルかつ満足できるものだと思いますか?しかし、いくつかの質問について考えてみましょう。

事前読み取りの失敗

上で、バッファ プールの先読みメカニズムによって隣接するデータ ページがプリロードされる可能性があることを説明しました。隣接する 2 つのデータ ページ 20 と 21 がロードされ、ページ番号 20 のキャッシュ ページのみがアクセスされ、他のキャッシュ ページはアクセスされないとします。このとき、両方のキャッシュ ページはリンク リストの先頭にありますが、この 2 つのキャッシュ ページをロードするために、末尾のキャッシュ ページが削除され、削除されたキャッシュ ページが頻繁にアクセスされます。この場合、事前読み取りが失敗し、バッファプールに事前ロードされたページにアクセスされません。これは不合理ではありませんか?

バッファプールの汚染
また、SQL 文を実行する際に、大量のデータをスキャンしたり、テーブル全体をスキャンしたりすると、大量のデータ ページがバッファー プールにロードされ、バッファー プール内の既存のページがすべて置き換えられるという状況もあります。この状況も不合理です。これはバッファプールの汚染であり、MySQL のパフォーマンスが大幅に低下する可能性があります。

ホットデータとコールドデータの分離

従来の LRU 方式では、バッファ プールのスペース管理要件を満たすことができないようです。そのため、Msyql は LRU に基づいてホット データとコールド データを分離するソリューションを設計しました。

つまり、LRU リンク リストは、ホット データ領域用とコールド データ領域用の 2 つの部分に分割されます。

データ ページが最初にバッファー プールにロードされると、コールド データ領域のリンク リストの先頭に配置されます。1 秒後 (innodb_old_blocks_time パラメータによって制御されます)、キャッシュ ページがアクセスされ、ホット データ領域のリンク リストの先頭に移動されます。

ホット データ領域に移動する前に 1 秒待たなければならないのはなぜかと疑問に思うかもしれません。考えてみてください。データ ページがコールド データ領域にロードされた直後にアクセスされ、二度とアクセスされない場合はどうなるでしょうか。これにより、ホットデータ領域が無駄になるのではないですか? 1 秒経ってもアクセスされない場合は、今後頻繁にアクセスされない可能性があるので、ホット バッファに移動する必要はありません。キャッシュ ページが不足している場合は、コールド データ領域からそれらを削除します。

別のケースでは、データ ページがすでにホット バッファー内にある場合、アクセスされる限り、キャッシュ ページはリンク リストの先頭に挿入されますか?言うまでもなく、それは無理だと思うに違いありません。ホット データ領域のキャッシュ ページは頻繁にアクセスされます。キャッシュ ページがアクセスされるたびにリンク リスト ヘッダーが挿入されると、ホット バッファー全体が非常に混乱した状態になります。その光景を想像してみてください。

では私たちは何をすべきでしょうか? MySQL では、ホット データ領域の最後の 3/4 は、アクセスされた後にのみリンク リストの先頭に移動されるように最適化されており、最初の 1/4 のキャッシュ ページはアクセスされた後に移動されません。

さて、バッファプールについては以上です。今回は、バッファ プールによって SQL 実行が高速化される理由と、バッファ プール領域の管理方法について説明しました。コメント欄での議論を歓迎します。

要約する

バッファプールの応用

バッファ プールは、ディスク I/O によるオーバーヘッドを大幅に削減します。データ行が操作されるデータ ページをバッファ プールにロードすることで、SQL の実行速度を向上させることができます。

バッファプールの事前読み取りメカニズム

ディスク I/O を削減するために、Innodb はバッファ プールで複数のデータ ページを事前に読み取ることによって最適化します。これを事前読み取りと呼びます。

バッファプールスペース管理

  • バッファ プールの従来の LRU 方式では、事前読み取りの失敗とバッファ プールの汚染という 2 つの状況が発生します。したがって、この従来の方法はバッファ プールのスペース管理には適していません。
  • Msyql は、LRU 方式の最適化に基づいて、ホット データとコールド データを分離するソリューションを設計し、LRU リンク リストをホット データ領域とコールド データ領域の 2 つの部分に分割して、事前読み取りの失敗とバッファー プールの汚染の問題を解決しました。

以上がMySQLのバッファプールの詳しい説明です。MySQLのバッファプールについてさらに詳しく知りたい方は、123WORDPRESS.COMの関連記事もぜひご覧ください!

以下もご興味があるかもしれません:
  • MySQL Innodbの主な機能挿入バッファ
  • MySQL クエリ キャッシュとバッファ プール
  • mysql 最適化のための重要なパラメータ key_buffer_size table_cache
  • mysql key_buffer_size設定を最適化する
  • mysql read_buffer_size の適切な設定は何ですか?
  • MySQL ソートが中止されました: ソート メモリが不足しています。サーバーのソート バッファ サイズを増やすことを検討してください。
  • MySQL ソースコードから Innodb バッファヒット率の計算を分析する
  • PHP での MySQL 操作バッファの使用法の詳細な説明
  • Mysql の最適化とチューニングにおける 2 つの重要なパラメータ: table_cache と key_buffer
  • mysql key_buffer_sizeパラメータの最適化設定
  • mysqldump によるバッファプール汚染の調査
  • MySQL 結合バッファの原理

<<:  XHTML 入門チュートリアル: XHTML とは何ですか?

>>:  VUE ユニアプリの基本コンポーネントの簡単な紹介

推薦する

koa2 サービスに SSL を設定する方法

I. はじめに1: SSL証明書私のドメイン名は Tencent Cloud にあります。第 3 レ...

IE6かどうかを判定する最短JS(IEの書き方)

ブラウザが IE のどのバージョンであるかを検出するためによく使用される JavaScript コー...

MySQL で準備、実行、割り当て解除ステートメントを使用するチュートリアル

序文MySQLでは、準備、実行、割り当て解除を正式にはPREPARE STATEMENTと呼びます。...

Linux IO 多重化 epoll ネットワーク プログラミング

序文この章では、基本的な Linux 関数と epoll 呼び出しを使用して、Linux 上で実行で...

Reactコンポーネントのライフサイクルの詳細な説明

目次1.ライフサイクルとは何か2. 読み込みプロセス1.コンストラクタ2. レンダリング3. コンポ...

Docker: /etc/default/docker の DOCKER_OPTS パラメータを変更しても反映されない

デフォルトでは、 /etc/default/docker 設定は有効になりません。docker 環境...

高度な JavaScript フロントエンド開発でよく使用されるいくつかの API の例の詳細な説明

目次ミューテーションオブザーバーAPI特徴インターセクションオブザーバーAPI例えば画像の遅延読み込...

Tcl言語に基づくシンプルなネットワーク環境を構成するプロセスの分析

1. Tclスクリプトファイルcircle.tclコードコメント #シミュレーションに必要なプロパテ...

MySQL の CPU 負荷が高い問題のトラブルシューティング

MySQL による CPU 負荷の上昇今日の午後、MySQL によってサーバーの負荷が高くなる問題を...

JavaScript イベント委任 (プロキシ) の使用例の詳細

目次導入例: イベントの委任記述方法1: イベント委譲書き方2: 各子要素がイベントをバインドする例...

Docker コンテナは実行後に終了します (実行を継続する方法)

現象Dockerコンテナを起動する docker run –name [コンテナ名] [コンテナID...

JavaScriptでページスクロールアニメーションを実装する

目次レイアウトを作成するCSSスタイルを追加するJavaScript で要素を操作する対象要素を取得...

jQueryはアコーディオン効果を実装します

この記事では、アコーディオンを実装するためのjQueryの具体的なコードを参考までに紹介します。具体...

JavaScript 高度なカスタム例外

目次1. コンセプト1.1 エラーと例外とは何ですか? 1.2 異常の分類2. 例外処理2.1try...

Vueは動的クエリルール生成コンポーネントを実装します

1. 動的クエリルール動的クエリルールは、おおよそ次の図のようになります。ユーザのカスタマイズに応じ...