高速クエリキャッシュは、Alibaba Cloud がネイティブの MySQL クエリキャッシュに基づいて開発したクエリキャッシュです。新しい設計と実装メカニズムを使用して、データベースのクエリパフォーマンスを向上させます。
前提条件
RDS インスタンスは、マイナーエンジンバージョンが 20200331 以降の MySQL 5.7 を実行していること。
RDS インスタンスの専用プロキシサービスが無効になっていること。詳細については、「ApsaraDB RDS for MySQL インスタンスの専用プロキシサービスを無効にする」をご参照ください。
背景情報
クエリキャッシュは、クエリ結果セットをキャッシュすることでパフォーマンスを向上させるメカニズムです。その中心的な原則は次のとおりです。
結果セットのキャッシュ: 対象となるクエリに対して、結果を直接キャッシュし、SQL の解析、最適化、実行プロセスの繰り返しを回避し、CPU のオーバーヘッドを削減します。
パフォーマンス目標: 計算リソースの消費を削減することで、高頻度の単純なクエリの応答時間を大幅に改善します。
ネイティブ MySQL クエリキャッシュの欠点
ネイティブの MySQL クエリキャッシュは、設計上の欠陥により、高い同時実行性シナリオではパフォーマンスが低下します。これには、次の問題が含まれます。
同時実行処理のパフォーマンスが低い。複数の CPU コアが構成されている場合、同時クエリの数が多いほどパフォーマンスが低下する可能性があります。
メモリ管理が不十分で、メモリ使用率が低く、回収が遅れるため、メモリの無駄遣いが発生します。
キャッシュヒット率が低い場合、クエリのパフォーマンスは向上せず、大幅に低下することさえあります。
これらの問題のため、ネイティブの MySQL クエリキャッシュは MySQL 8.0 で完全に削除され、以前のバージョンではデフォルトで無効になっていました。
Alibaba Cloud 高速クエリキャッシュの革新的な改善点
Alibaba Cloud データベースチームは、ネイティブのクエリキャッシュの欠点に対処するために高速クエリキャッシュを再設計および実装し、次の主要な最適化を行いました。
改善領域 | 具体的な対策 |
同時実行パフォーマンスの最適化 | グローバルロックを削除し、ロックフリー設計とシャーディングメカニズムを採用して、マルチコア並列処理を可能にし、ロック競合を排除しました。 |
メモリ管理の最適化 | 動的メモリ割り当てを導入し、必要に応じてメモリを割り当て、インテリジェントな回収ポリシーと組み合わせて断片化を減らし、使用率を向上させました。 |
動的キャッシュポリシーの調整 | キャッシュヒット率とビジネスシナリオをリアルタイムで監視し、キャッシュポリシー (エビクション戦略、キャッシュの有効期間など) を動的に調整して、無効なキャッシュがリソースを占有するのを防ぎます。 |
書き込み操作の互換性 | 増分無効化メカニズムを通じて、影響を受けるクエリキャッシュのみを部分的に無効にし、書き込み操作がキャッシュに与える影響を軽減します。 |
高速クエリキャッシュは、幅広いビジネスシナリオで使用してクエリパフォーマンスを向上させることができます。ただし、ネイティブの MySQL クエリキャッシュは、同じレベルのサポートを提供していません。
高速クエリキャッシュを有効にする
ApsaraDB RDS コンソールで [query_cache_type] および [query_cache_size] パラメーターを構成することで、高速クエリキャッシュを有効にできます。
パラメーター | 説明 |
query_cache_type | 高速クエリキャッシュを制御するために使用されるスイッチ。有効値:
|
query_cache_size | 高速クエリキャッシュに割り当てられるメモリ領域のサイズ。有効値: 0~10485760000。値は 1024 の倍数である必要があります。単位: バイト。 |
高速クエリキャッシュは追加のメモリ領域を占有します。高速クエリキャッシュを構成する際には、[innodb_buffer_pool_size] パラメーターも再構成することをお勧めします。
[innodb_buffer_pool_size] パラメーターをこのパラメーターの元の値の 90% に設定します。削減された 10% のメモリ領域は、[query_cache_size] パラメーターで指定されるクエリキャッシュサイズとして使用されます。たとえば、innodb_buffer_pool_size パラメーターの元の値が {DBInstanceClassMemory*7/10} の場合、このパラメーターを {DBInstanceClassMemory*63/100} に設定します。詳細については、「InnoDB バッファープールのサイズを変更する」をご参照ください。
[query_cache_size] パラメーターを設定します。詳細については、「インスタンスパラメーターの変更」をご参照ください。
結果セットのサイズを正確に見積もることができる場合は、[query_cache_size] パラメーターを
結果セットサイズの 20%と等しい値に設定できます。結果セットのサイズを正確に見積もることができない場合は、[query_cache_size] パラメーターを
innodb_buffer_pool_size パラメーターの値の 10%と等しい値に設定できます。
説明RDS インスタンスの仕様を変更しても、[query_cache_size] パラメーターの値は新しい仕様に基づいて変更されません。仕様の変更が適用された後、このパラメーターを直ちに再構成する必要があります。
[query_cache_type] パラメーターを [1] に設定します。これにより、高速クエリキャッシュを有効にできます。詳細については、「インスタンスパラメーターの変更」をご参照ください。
パフォーマンスの比較
さまざまなテストケースで、同じ条件下で異なるクエリキャッシュ構成のクエリ/秒 (QPS) を比較します。これらのクエリキャッシュ構成は、QC-OFF (クエリキャッシュが有効になっていない)、MySQL-QC (ネイティブの MySQL クエリキャッシュが有効になっている)、および Fast-QC (高速クエリキャッシュが有効になっている) です。
テスト環境: 4 CPU コアと 8 GB のメモリを搭載した専用 RDS インスタンス
テストツール: Sysbench
テストデータサイズ: 250 MB (合計 25 テーブル、各テーブル 40,000 レコード)
シナリオ 1: すべてヒット (読み取り専用)
oltp_point_select スクリプトが使用されます。プライマリキーに基づく POINT SELECT 文のみを実行します。さらに、クエリキャッシュサイズを 512 MB に設定してください。このサイズはテストデータサイズよりも大きく、キャッシュヒット率が 100% に達することを可能にします。このテストケースでは、同時クエリの数に基づいて QPS がどれだけ増加するかに焦点を当てます。
表 1. キャッシュヒット率 100% の読み取りクエリの QPS
同時クエリ数
QC-OFF
MySQL-QC (QC-OFF と比較した QPS 増加率)
Fast-QC (QC-OFF と比較した QPS 増加率)
1
8,093
8,771 (8.38%)
9,261 (14.43%)
8
62,262
65,686 (5.50%)
75,313 (20.96%)
16
97,083
73,027 (-24.78%)
139,323 (43.51%)
32
97,337
60,567 (-37.78%)
200,978 (106.48%)
64
106,283
60,216 (-43.34%)
221,659 (108.56%)
128
107,781
62,844 (-41.69%)
231,409 (114.70%)
256
106,694
63,832 (-40.17%)
222,187 (108.25%)
512
101,733
64,866 (-36.24%)
203,789 (100.32%)
1,024
89,548
62,291 (-30.44%)
203,542 (127.30%)
説明テスト結果に基づくと、同時クエリの数が増加するにつれて、ネイティブの MySQL クエリキャッシュの QPS は大幅に減少します。しかし、高速クエリキャッシュの QPS は減少しないどころか、最大で 100% 増加することもあります。
シナリオ 2: 高いヒット率 (読み取り専用)
テストシナリオは Sysbench oltp_read_only です。このユースケースには、複数のレコードを返す範囲クエリが含まれます。クエリキャッシュが 512 MB に設定されている場合、メモリは比較的に十分であり、ヒット率は 80% を超えることがあります。このテストでは、さまざまな同時負荷下でのパフォーマンス向上に焦点を当てます。
表 2. キャッシュヒット率が 80% を超える読み取りクエリの QPS
同時クエリ数
QC-OFF
MySQL-QC (QC-OFF と比較した QPS 増加率)
Fast-QC (QC-OFF と比較した QPS 増加率)
1
5099
6467 (26.83%)
7022 (37.71%)
8
28782
28651 (-0.46%)
45017 (56.41%)
16
35333
31099 (-11.98%)
66770 (88.97%)
32
34864
27610 (-20.81%)
67623 (93.96%)
64
35503
27518 (-22.49%)
75981 (114.01%)
128
35744
27733 (-22.41%)
80396 (124.92%)
256
35685
27738 (-22.27%)
80925 (126.78%)
512
35308
27398 (-22.40%)
79323 (124.66%)
1024
34044
26861 (-22.10%)
75742 (122.48%)
説明テスト結果に基づくと、同時クエリの数が増加するにつれて、ネイティブの MySQL クエリキャッシュの QPS は大幅に減少します。しかし、高速クエリキャッシュの QPS は増加し続け、ピーク時には 100% 以上増加することもあります。
テストケース 3: キャッシュヒット率が約 10% の読み取りクエリの QPS をテストする
oltp_read_only スクリプトが使用されます。それぞれが複数のレコードを返す範囲クエリを含むクエリを実行します。さらに、クエリキャッシュサイズを 16 MB に設定してください。このサイズではメモリ領域が不足し、大量のキャッシュデータが削除されます。これにより、キャッシュヒット率が約 10% に低下します。このテストケースでは、同時クエリの数に基づいて QPS がどれだけ減少するかに焦点を当てます。
表 3. キャッシュヒット率が約 10% の読み取りクエリの QPS
同時クエリ数
QC-OFF
MySQL-QC (QC-OFF と比較した QPS 増加率)
Fast-QC (QC-OFF と比較した QPS 増加率)
1
5,004
4,727 (-5.54%)
5,199 (3.90%)
8
28,795
22,542 (-21.72%)
28,578 (-0.75%)
16
35455
24,064 (-32.13%)
35,682 (0.64%)
32
34,526
21,330 (-38.22%)
35,871 (3.90%)
64
35,514
19,791 (-44.27%)
36,051 (1.51%)
128
35,983
19,519 (-45.75%)
36,253 (0.75%)
256
35,695
19,168 (-46.30%)
36,337 (1.80%)
512
35,182
18,420 (-47.64%)
35,972 (2.25%)
1,024
33,915
20,168 (-40.53%)
34,546 (1.86%)
説明テスト結果に基づくと、ネイティブの MySQL クエリキャッシュの QPS は大幅に減少し、パフォーマンスの損失は最大で 50% に近づきます。しかし、高速クエリキャッシュは低いヒット率のシナリオを最適化し、追加のパフォーマンス損失をほとんど引き起こしません。
テストケース 4: 読み取りおよび書き込みクエリの QPS をテストする。
oltp_read_write スクリプトが使用されます。テーブルの更新を含むトランザクションを実行します。これらの頻繁な更新により、キャッシュデータが削除されます。その結果、構成されたクエリキャッシュは無効と見なされます。このテストケースでは、同時クエリの数に基づいて QPS がどれだけ減少するかに焦点を当てます。
表 4. 読み取りおよび書き込みクエリの QPS
同時クエリ数
QC-OFF
Fast-QC (QC-OFF と比較した QPS 増加率)
1
4,152
4,098 (-1.30%)
8
21,359
21,195 (-0.77%)
16
26,020
25,548 (-1.81%)
32
27,595
26,996 (-2.17%)
64
29,229
28,733 (-1.70%)
128
29,265
28,828 (-1.49%)
256
29,911
29,616 (-0.99%)
512
29,148
28,816 (-1.14%)
1,024
29,204
28,824 (-1.30%)
説明テスト結果に基づくと、同時読み取りおよび書き込みクエリの数が増加するにつれて、高速クエリキャッシュの QPS はわずかに減少するだけです。
実践ガイドライン
シナリオ
高速クエリキャッシュは、主に読み取り集中型のシナリオでパフォーマンスを向上させるために使用されます。書き込みよりも読み取りが大幅に多い環境に推奨されます。
主にクエリベースで書き込み頻度が低いビジネス操作 (eコマースの製品詳細ページ、レポートクエリなど)。
SQL_CACHEを使用して、特定のテーブル (読み取り/書き込み比率が高いテーブルなど) のキャッシュを明示的に有効にします。TABLE_STATISTICS テーブルを通じてテーブルレベルの読み取り/書き込み比率を表示し、読み取り/書き込み比率が高いテーブルに対して SQL_CACHE キーワードを使用して高速クエリキャッシュを明示的に有効にすることもできます。TABLE_STATISTICS テーブルのクエリに関する情報については、「パフォーマンスインサイト」をご参照ください。
次の場合は推奨されません。
書き込み集中型のシナリオ (高頻度のトランザクションシステムなど): 頻繁なキャッシュ無効化により、パフォーマンスが低下する可能性があります。
高いデータのリアルタイム精度を必要とするシナリオ (株式市場の相場など): キャッシュされたデータがリアルタイムデータと一致しない場合があります。
グローバルに有効にする前に、InnoDB バッファープールのヒット率 (ヒット率 = 1 - Innodb_buffer_pool_reads/Innodb_buffer_pool_read_requests) を確認することをお勧めします。ヒット率が 80% 未満の場合、高速クエリキャッシュを有効にすることはお勧めできません。
キャッシュの使用方法 (Query_cache_type)
[query_cache_type] パラメーターはセッションレベルの変更をサポートしています。ユーザーは実際のビジネスシナリオに基づいて柔軟に構成できます。次の推奨事項をご参照ください。
パラメーター値 | 説明 | 適用シナリオ |
0 | 高速クエリキャッシュをグローバルに無効にする | 書き込み集中型のシナリオまたはキャッシュヒット率が極端に低いシナリオ |
1 | グローバルに有効にし、すべての対象クエリを自動的にキャッシュする | データ更新頻度が低い読み取り集中型のシナリオ |
2 | 明示的な | 大量のデータ、不安定なアクセスパターン、または詳細な制御が必要なシナリオ |
キャッシュサイズ (Query_cache_size) の設定
[query_cache_size] は SQL クエリと密接に関連しています。キャッシュに複数のレコードを返すクエリが含まれている場合、キャッシュはデータ量の数倍の大きさが必要になることがあります。SQL クエリに範囲クエリが含まれていない場合は、次のテストを参照して、データ量と [query_cache_size] の関係を評価できます。
テスト環境: 4 CPU コアと 8 GB のメモリを搭載した専用 RDS インスタンス (innodb_buffer_pool_size = 6 GB)
テストツール: Sysbench
テストデータサイズ: 10 GB (合計 100 テーブル、各テーブル 400,000 レコード)
テストケース: query_cache_size パラメーターを使用して異なるキャッシュサイズを指定し、各キャッシュサイズに対して oltp_point_select スクリプトを実行します。64 スレッドが同時に実行されてデータをクエリするようにします。この場合、テストデータには 20% のホットデータが含まれます。これにより、異なるキャッシュサイズ ([query_cache_size]) が QPS に与える影響を把握できます。テストデータに基づくと、実際の結果セットサイズは 2.5 GB です。
表 5. 異なるキャッシュサイズでの QPS
query_cache_size (MB) | QC-OFF | Fast-QC ヒット率 | Fast-QC (QC-OFF と比較した QPS 増加率) |
64 | 98,236 | 22% | 99,440 (1.23%) |
128 | 98,236 | 45% | 114,155 (16.21%) |
256 | 98,236 | 72% | 140,668 (43.19%) |
512 | 98,236 | 82% | 151,260 (53.98%) |
1,024 | 98,236 | 84% | 153,866 (56.63%) |
2,048 | 98,236 | 87% | 159,597 (62.46%) |
4,096 | 98236 | 92% | 169,412 (72.45%) |
高速クエリキャッシュのパフォーマンスは、[query_cache_size] パラメーターの値に関係なく低下しません。具体的には、高速クエリキャッシュは、キャッシュヒット率に関係なく、プライマリキークエリに対してネイティブの MySQL クエリキャッシュよりも大幅に高いパフォーマンスを提供します。状況によっては、パフォーマンスが 90% 以上向上することもあります。キャッシュヒット率が 90% 未満の場合、高速クエリキャッシュはネイティブの MySQL クエリキャッシュよりも高いパフォーマンスを提供し、範囲クエリや ORDER BY 句を含むクエリに対して多くの CPU リソースを節約します。