https://blog.csdn.net/weixin_40009393/article/details/111103350
アプリケーションシステムの階層化アーキテクチャは、データアクセスを高速化するために、最も頻繁にアクセスされるデータをキャッシュに格納して、毎回データベースにアクセスしないようにします。
オペレーティングシステムには、データアクセスを高速化するために毎回ディスクへのアクセスを回避するためのバッファプールメカニズムがあります。
ストレージシステムとして、MySQLには、データがクエリされるたびにディスクIOを回避するバッファプールメカニズムもあります。
今日は、InnoDBのバッファープールについてお話します。
InnoDBのバッファープールキャッシュとは何ですか?用途は何ですか?
テーブルデータとインデックスデータをキャッシュし、ディスク上のデータをバッファプールにロードし、アクセスごとにディスクIOを回避し、アクセスを高速化する役割を果たします。
速度が速いので、すべてのデータをバッファプールに入れてみませんか?
すべてに2つの側面があります。データの変動性に関係なく、高速アクセスの反対はストレージ容量が小さいことです。
(1)キャッシュアクセスは高速ですが、容量は小さいです。データベースには200Gのデータが格納され、キャッシュ容量は64Gのみです。
(2)メモリアクセスは高速ですが、容量は小さいです。2Tのノートブックディスクを購入した場合、メモリは16Gしかない場合があります。
したがって、「最もホットな」データのみを「最近の」場所に配置して、ディスクアクセスを「最大」レベルに減らすことができます。
パフォーマンスを最大化するためにバッファプールを管理および排除する方法は?
具体的な詳細を紹介する前に、「先読み」の概念を紹介しましょう。
先読みとは何ですか?
ディスクの読み取りと書き込みはオンデマンドでは読み取られませんが、ページごとに読み取られます。一度に少なくとも1ページのデータ(通常は4K)が読み取られます。将来読み取られるデータがページ内にある場合、後続のディスクIOは次のようになります。省略、効率向上。
なぜ先読みが効果的ですか?
データアクセスは通常、「集中型の読み取りと書き込み」の原則に従います。一部のデータを使用すると、近くのデータが使用される可能性が高くなります。これはいわゆる「局所性の原則」であり、早期の読み込みが効果的であり、実際にディスクIOを削減します。
ページごと(4K)の読み取りとInnoDBのバッファープールの設計との関係は何ですか?
(1)ページごとのディスクアクセス読み取りはパフォーマンスを向上させることができるため、バッファプールは通常ページごとにデータをキャッシュします。
(2)先読みメカニズムにより、将来のディスクIO操作を回避するために、事前に「アクセスされる可能性がある」ページをバッファプールに追加するようになりました。
InnoDBはこれらのバッファページを管理するためにどのアルゴリズムを使用しますか?
考えるのが最も簡単なのはLRU(最近使用されていない)です。
Voiceover:MemcacheとOSはページ置換管理にLRUを使用しますが、MySQLのゲームプレイは異なります。
従来のLRUはバッファページをどのように管理しますか?
最も一般的な再生方法は、LRUの先頭にあるバッファプールにページを最後にアクセスされた要素として配置することです。これにより、遅くとも削除されます。2つの状況があります:
(1)ページはすでにバッファプールにあり、LRUヘッドに「移動」するアクションのみが実行され、ページは削除されません。
(2)ページがバッファプールにない場合、LRUの先頭を「挿入」するアクションに加えて、LRUの末尾ページを「削除」するアクションも必要です。
上の図に示すように、管理バッファー・プールのLRU長が10の場合、ページ番号1、3、5 ...、40、7のページがバッファーに入れられます。
次にアクセスするデータがページ番号4のページにあるとします。
(1)ページ番号4のページは、元々バッファー・プールにあります。
(2)ページ番号4のページをLRUの先頭に配置すると、ページが削除されません。
ナレーション:データの移動を減らすために、LRUは通常リンクリストで実装されます。
次にアクセスするデータがページ番号50のページにあるとします。
(1)ページ番号50のページは、元々バッファー・プールにありませんでした。
(2)ページ番号50のページをLRUの先頭に配置し、同時にページ番号7のページを最後に削除します。
従来のLRUバッファプールアルゴリズムは非常に直感的です。OSやmemcacheなどの多くのソフトウェアがすべて使用されています。MySQLが非常に偽善的で直接使用できないのはなぜですか。
ここには2つの問題があります。
(1)先読みに失敗します。
(2)バッファープールの汚染。
先読み障害とは何ですか?
先読みのため、ページは事前にバッファプールに入れられますが、最終的にMySQLはページからデータを読み取らないため、先読み障害と呼ばれます。
先読み障害を最適化する方法は?
先読み障害を最適化するためのアイデアは次のとおりです。
(1)先読みに失敗したページを、バッファプールLRUにできるだけ短くとどまらせます。
(2)実際に読み取られるページをバッファプールLRUの先頭に移動させます。
実際に読み取られるホットデータが可能な限りバッファプールにとどまるようにするため。
具体的な方法は次のとおりです。
(1)LRUを2つの部分に分割します。
- 新世代(新サブリスト)
- 古いサブリスト
(2)新世代と旧世代は最後に接続されます。つまり、新世代のテールは旧世代のヘッドに接続されます。
(3)新しいページ(先読みページなど)がバッファープールに追加されると、それらは古い世代の先頭にのみ追加されます。
- データが実際に読み取られた場合(先読みが成功した場合)、データは新世代の先頭に追加されます
- データが読み取られない場合、新世代の「ホットデータページ」よりも早くバッファプールから削除されます。
たとえば、バッファプールLRU全体は次のようになります。
(1)LRU全体の長さは10です。
(2)最初の70%は新世代です。
(3)最後の30%は古い世代です。
(4)新旧の世代は端から端までつながっています。
ページ番号50の新しいページが先読みされ、バッファプールに追加された場合:
(1)50は旧世代の先頭からのみ挿入され、旧世代の終わりのページ(および全体の末尾)は削除されます。
(2)ページ50が実際に読み取られない、つまり先読みが失敗したとすると、新世代のデータよりも早くバッファプールから削除されます。
たとえば、ページ50がすぐに読み取られると、SQLはページ内の行データにアクセスします。
(1)すぐに新世代の頭に追加されます。
(2)新世代のページは旧世代に圧縮され、現時点で実際に削除されるページはありません。
改善されたバッファプールLRUは、「先読み障害」の問題を解決できます。
ナレーション:しかし、窒息のために食事をやめないでください。また、先読みの失敗を恐れているため、先読み戦略をキャンセルしてください。ほとんどの場合、局所性の原則は有効であり、先読みは効果的です。
改良されたLRUの新旧世代は、バッファプールの汚染の問題をまだ解決できません。
MySQLバッファプールの汚染とは何ですか?
特定のSQLステートメントが大量のデータをバッチでスキャンする必要がある場合、バッファプールのすべてのページが置き換えられ、大量のホットデータがスワップアウトされ、MySQLのパフォーマンスが大幅に低下する可能性があります。バッファプール汚染と呼ばれます。
たとえば、大量のデータを含むユーザーテーブルがある場合、実行すると次のようになります。
select * from user where name like "%shenjian%";
結果セットには少量のデータしかない場合がありますが、このタイプのようなものはインデックスにヒットできません。全表スキャンが必要であり、多数のページにアクセスする必要があります。
(1)ページをバッファプールに追加します(古い世代のヘッドを挿入します)。
(2)ページから関連する行を読み取ります(新世代の頭を挿入します)。
(3)行の名前フィールドが文字列shenjianと比較され、条件を満たしている場合は結果セットに追加されます。
(4)...すべてのページのすべての行がスキャンされるまで...
このようにして、すべてのデータページが新世代のヘッドにロードされますが、アクセスは1回だけであり、実際のホットデータは大量にスワップアウトされます。
大量のデータをスキャンすることによって引き起こされるこの種のバッファプール汚染問題はどうですか?
MySQLバッファプールには、「旧世代の滞留時間ウィンドウ」のメカニズムが追加されています。
(1)T =旧世代の滞留時間ウィンドウと仮定します。
(2)旧世代の先頭に挿入されたページは、すぐにアクセスしても新世代の先頭には配置されません。
(3)「訪問」の要件を満たし、「旧世代の滞在時間」がTより大きい場合にのみ、若い世代の頭に入れられます。
例を続けると、バッチデータがスキャンされると、51、52、53、54、55などの5つのページに順番にアクセスされます。
「旧世代の滞留時間ウィンドウ」戦略がない場合、バッチでアクセスされるこれらのページは、大量のホットデータをスワップアウトします。
「旧世代滞在時間枠」戦略を追加した後、短時間で大量に読み込まれるページはすぐに新世代のヘッドに挿入されませんが、短期間に一度だけアクセスされたページは時間が最初に削除されます。
そして、古い世代が十分に長く滞在し、滞在時間がTより大きい場合にのみ、それは若い世代の頭に挿入されます。
上記の原則は、InnoDBのどのパラメーターに対応していますか?
さらに3つの重要なパラメータがあります。
参数:innodb_buffer_pool_size
はじめに:バッファプールのサイズを構成します。メモリが許可されている場合、DBAはこのパラメータを増やすことを推奨することがよくあります。メモリに配置されるデータとインデックスが多いほど、データベースのパフォーマンスが向上します。
パラメーター:innodb_old_blocks_pct
はじめに:LRUチェーン全体の長さに対する古い世代の比率はデフォルトで37です。つまり、LRU全体の古い世代に対する若い世代の長さの比率は63:37です。
ナレーション:このパラメーターが100に設定されている場合、通常のLRUに縮退します。
パラメーター:innodb_old_blocks_time
はじめに:旧世代の滞在時間ウィンドウ、単位はミリ秒、デフォルトは1000です。つまり、「訪問済み」と「滞在」の2つの条件がある場合にのみ、新世代の先頭に挿入されます。 1秒を超える旧世代」が同時に出会う。
総括する
(1)バッファプールは、ディスクアクセスを減らすための一般的なメカニズムです。
(2)バッファプールは通常、ページ単位でデータをキャッシュします。
(3)バッファープールの一般的な管理アルゴリズムはLRU、memcache、OS、InnoDBであり、すべてこのアルゴリズムを使用します。
(4)InnoDBは通常のLRUを最適化します。
- バッファプールは、古い世代と若い世代に分けられます。バッファプールに入るページは、最初に古い世代に入り、新しい世代に入る前にページにアクセスして、先読みエラーの問題を解決します。
- バッチデータアクセスと大量のホットデータの排除の問題を解決するために、ページがアクセスされ、古い世代で費やされた時間が新しい世代に入る前に構成されたしきい値を超えます
アイデアは結論よりも重要です。
どの問題を解決するかは、解決よりも重要です。