SQLの実行速度を向上させる方法は?
データを更新する場合、データをディスクからロードし、更新後にディスクに保持しますか?
これを行うと、大きなディスクファイルの読み取りおよび書き込み操作に数百万ミリ秒かかるため、そのSQLの実行プロセスは遅すぎます。
実際の実行プロセスでは、データを更新または読み取りたいときに、対応するページをバッファプールにロードします(バッファプールは基本的に連続したメモリスペースです)。
デフォルトは128mです。もちろん、システムの同時実行性を向上させるために、この値をより大きな値に設定できます。
ページがバッファプールにロードされる理由は、このページの他のデータがこのページのデータを使用するときに使用します。ページは非常に大きく、ランダムIOに時間がかかるため、バッファプールにもう少しデータをロードします。
バッファプールのデータ構造は何ですか?
バッファプールは、主にキャッシュページと説明データの2つの部分に分かれています。MySQLによってディスクからロードされたデータページは、キャッシュページに配置されます。
キャッシュ・ページごとに、データ・ページが属する表スペース、データ・ページの番号など、対応する説明情報があります。
バッファプール内の記述データは、キャッシュページサイズの約5%にほぼ相当します。メモリのこの部分は、バッファプールに含まれていません。
データを更新するときに、対応するページがバッファプールにある場合は、バッファプール内のページを直接更新できます。対応するページがバッファプールにない場合、対応するページがディスクからバッファプールにロードされます。この時点で、バッファプール内のページデータは、ダーティページと呼ばれるディスク内のページデータと一致していません。これらのダーティページはディスクにフラッシュバックされます
これらのダーティページはどのくらいの頻度でディスクにフラッシュバックされますか?次の時間があります
- バッファプールが十分ではありません。新しくロードされたページ用のスペースを確保する必要があるため、改善されたLRUアルゴリズムを使用して、ダーティページをディスクにフラッシュします。
- MySQLがビジーでない場合、バックグラウンドスレッドはダーティページをディスクにフラッシュします
- やり直しがいっぱいになったとき(やり直しの役割については後で説明します)
- データベースがシャットダウンされると、すべてのダーティページがディスクにフラッシュバックされます
これはそれをはるかに効率的にしますか?
更新するデータが配置されているページがすでにバッファプールにある場合は、メモリを操作するだけでよく、効率は一般的に高くありません。
どのキャッシュページが空いているかをどうやって知ることができますか?
MySQLは、二重リンクリストであるバッファプールの無料リンクリストを設計しました。各ノードは、無料キャッシュページの説明データです。
キャッシュページがメモリにロードされているかどうかを確認するにはどうすればよいですか。
非常に簡単です。ハッシュテーブルを作成するだけです。キーはテーブルスペース番号+ページ番号で、値は対応するキャッシュページです。
データページがキャッシュページに読み込まれると、対応する説明データがフリーリンクリストからフラッシュリンクリストに配置されます。
ディスク上のデータページがキャッシュページに継続的にロードされると、フリーリンクリストはフリーキャッシュページを削除し続けます。フリーリンクリストにフリーキャッシュページがない場合、データページをキャッシュにロードする場合ページ、あなたは何をすべきですか?ウールの布?
一部のデータを削除したい場合、誰を削除する必要がありますか?
LRUリンクリストを導入して、一般的に使用されていないキャッシュページを特定しますか?
キャッシュ除去戦略は多くのミドルウェアで使用されています。最も使用されているのはLRUアルゴリズムです。キャッシュページにアクセスするたびに、キャッシュページはリンクリストの先頭に移動します。
最後にキャッシュページをフラッシュするだけで済みます。リンクリストのメモリに挿入し、新しいデータページをロードします。
この方法は完璧に見えますが、実際の操作プロセスには大きな隠れた危険があります
1つ目は、mysqlの先読みです。
どのような状況がMySQLの先読みをトリガーしますか
全表スキャンが発生すると(ユーザーからのselect *など)、テーブル内のすべてのデータページがバッファプールにロードされます。これにより、LRUリンクリストの前にある大量のデータページが全表スキャンによってロードされたデータページになる可能性がありますが、この全表スキャン後にこのテーブルのデータがほとんど使用されない場合はどうなりますか?
これにより、頻繁にスキャンされるキャッシュページが削除され、全表スキャンによってロードされたキャッシュページのみが残ります。
この問題を解決するために、LRUリンクリストが改善され、ホットとコールドを分離するというアイデアが採用されています。
つまり、LRUリンクリストは2つの部分に分割され、1つはコールドデータで、もう1つはホットデータです。
改善されたリンクリストはどのように機能しますか?
データページが最初にキャッシュにロードされると、キャッシュされたページはコールドデータ領域のリンクリストの先頭に配置されます。
では、コールドデータ領域のキャッシュページはホットデータ領域にいくつ配置されますか?
コールドデータ領域のキャッシュページに再度アクセスしたときに、ホットデータ領域に配置できるかどうかを考えているかもしれません。
mysql> SHOW VARIABLES LIKE 'innodb_old_blocks_pct';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_old_blocks_pct | 37 |
+-----------------------+-------+
1 row in set (0.02 sec)
複数のスレッドがバッファプール内のさまざまなリンクリストにアクセスする場合、スレッドセーフを確保するためにロックする必要があります。これは、リクエストの処理速度に影響します。このとき、バッファプールを複数のスレッドに分割し、マルチスレッドアクセスを行うことができます。相互に影響を与えないため、リクエストの処理速度が向上
します。MySQL5.7.5より前は、バッファプールを動的に拡張したり、動的に拡張したりすることはできませんでした。動的拡張を増やすために、チャンクメカニズムが追加されました。興味のあるパートナーは他の情報を見ることができるので、これ以上の分析は行いません。
リファレンスブログ
[1]