すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB RDS:Fast Query Cache

最終更新日:Aug 22, 2026

Fast Query Cache は、Alibaba Cloud が開発したクエリキャッシュで、MySQL ネイティブのクエリキャッシュをロックフリーで高い同時実行性を持つ設計に置き換えるものです。読み取り負荷の高いワークロードにおいて 1 秒あたりのクエリ数 (QPS) を大幅に向上させる一方、読み取りと書き込みが混在するシナリオでは追加するオーバーヘッドは最小限です。

Fast Query Cache は、マイナーエンジンバージョンが 20200331 以降の MySQL 5.7 を実行している ApsaraDB RDS for MySQL インスタンスで、かつ専用プロキシサービスが無効化されている場合にのみ利用可能です。

前提条件

開始する前に、以下を確認してください。

仕組み

クエリキャッシュは、条件を満たすクエリの結果セットを保存することでパフォーマンスを向上させます。同じクエリが再度実行されると、データベースはキャッシュされた結果を直接返すため、SQL の解析、最適化、実行をスキップできるため、高頻度かつシンプルなクエリにおける CPU オーバーヘッドと応答時間が削減されます。

MySQL ネイティブのクエリキャッシュを使用しない理由

MySQL ネイティブのクエリキャッシュは、すべてのキャッシュ操作にグローバルロックを使用します。高い同時実行性環境下では、このロックがボトルネックとなります。CPU コアを追加しても、QPS が向上するどころか低下することがあります。メモリ管理の不備がこの問題をさらに悪化させます。断片化の蓄積、回収の遅延、キャッシュヒット率の低さが、大幅なパフォーマンス低下を引き起こします。これらの問題により、MySQL は MySQL 8.0 でネイティブのクエリキャッシュを完全に廃止し、それ以前のバージョンではデフォルトで無効にしました。

Fast Query Cache がこれらの問題を解決する方法

Alibaba Cloud は、クエリキャッシュをゼロから再設計しました。

改善領域 変更内容
同時実行性 グローバルロックを削除しました。シャーディングを伴うロックフリー設計を採用し、ロック競合のない真のマルチコア並列処理を実現しています。
メモリ管理 オンデマンドでメモリを割り当てます。インテリジェントな回収ポリシーにより、断片化を削減し、メモリ使用率を向上させます。
キャッシュポリシー キャッシュヒット率をリアルタイムで監視し、エビクションポリシーとキャッシュ有効期間を動的に調整することで、古いエントリがリソースを占有するのを防ぎます。
書き込み互換性 増分無効化を使用して、書き込みの影響を受けたキャッシュエントリのみを部分的に無効化し、キャッシュされた読み取りへの影響を軽減します。

Fast Query Cache の有効化

Fast Query Cache は、query_cache_type (オン/オフスイッチ) と query_cache_size (メモリ割り当て) の 2 つのパラメーターで制御します。

パラメーター

パラメーター 説明
query_cache_type キャッシュの有効/無効を制御します。有効な値: 0 — 無効 (デフォルト)、1 — 条件を満たすすべてのクエリで有効になります (SQL_NO_CACHE でステートメントごとにキャッシュを無効化できます)、2 — グローバルでは無効ですが、SQL_CACHE で特定のステートメントのキャッシュを有効化できます
query_cache_size キャッシュに割り当てるメモリサイズ。有効な値: 0 ~ 10,485,760,000 バイト (1,024 の倍数である必要があります)。単位: バイト

手順

Fast Query Cache は追加のメモリを消費するため、まず innodb_buffer_pool_size を再設定してメモリの空き容量を確保します。

  1. innodb_buffer_pool_size を現在の値の 90% に削減します。これにより解放された 10% をクエリキャッシュに利用できます。たとえば、現在の値が {DBInstanceClassMemory*7/10} の場合、{DBInstanceClassMemory*63/100} に設定します。詳細については、「InnoDB バッファープールサイズの変更」をご参照ください。

  2. ワークロードに基づいて query_cache_size を設定します。パラメーターの変更の詳細については、「インスタンスパラメーターの変更」をご参照ください。

    • 結果セットのサイズがわかっている場合: query_cache_size結果セットサイズの 20% に設定します。

    • 結果セットのサイズがわからない場合: query_cache_size を [innodb_buffer_pool_size の 10%] に設定します。

    重要

    ApsaraDB RDS for MySQL インスタンスの仕様を変更しても、query_cache_size は自動的にスケーリングされません。仕様変更が有効になった直後に、このパラメーターを再設定してください。

  3. query_cache_type を [1] に設定して、Fast Query Cache を有効にします。詳細については、「インスタンスパラメーターの変更」をご参照ください。

セッションレベルでのテスト

グローバル設定を変更する前に、他のユーザーに影響を与えることなく、単一の接続で Fast Query Cache をテストできます。

-- このセッションでのみ Fast Query Cache を有効にする
SET SESSION query_cache_type = 1;

-- このセッションでのみ Fast Query Cache を無効にする
SET SESSION query_cache_type = 0;

キャッシュが機能していることの確認

Fast Query Cache を有効にした後、次のステートメントを実行してキャッシュの動作状況を確認します。

SHOW STATUS LIKE 'Qcache%';

確認すべき主な指標は次のとおりです。

指標 内容
Qcache_hits キャッシュから返されたクエリの数。この値が増加していれば、キャッシュが機能していることを確認できます。
Qcache_inserts キャッシュに追加されたクエリの数
Qcache_lowmem_prunes メモリ不足により削除されたキャッシュエントリの数。この値が高い場合は、query_cache_size の設定値が小さすぎることを示します。
Qcache_not_cached キャッシュされなかったクエリの数 (キャッシュ対象外のクエリ、または SQL_NO_CACHE が指定されたクエリ)

キャッシュが正常に機能している場合、Qcache_hitsQcache_inserts よりも速く増加します。

パフォーマンスベンチマーク

以下のベンチマークは、専用 ApsaraDB RDS for MySQL インスタンス (4 CPU コア、8 GB メモリ、Sysbench を使用した 250 MB のテストデータ) における 3 つの構成での QPS を比較したものです。

  • QC-OFF: クエリキャッシュなし

  • MySQL-QC: MySQL ネイティブのクエリキャッシュ

  • Fast-QC: Fast Query Cache

全ヒットの読み取りワークロード (100% キャッシュヒット率、512 MB キャッシュ)

プライマリキーに対する POINT SELECT ステートメントを使用した oltp_point_select スクリプトを使用します。

表 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 は急激に低下し、64 スレッドで最大 43% 減少します。一方、Fast Query Cache の QPS は上昇を続け、1,024 スレッドで QC-OFF を最大で 127.30% 上回ります。

高ヒット率の読み取りワークロード (80% 以上のキャッシュヒット率、512 MB キャッシュ)

複数のレコードを返す範囲クエリを使用した oltp_read_only スクリプトを使用します。

表 2. キャッシュヒット率 80% 以上での読み取りクエリの QPS

同時クエリ数 QC-OFF MySQL-QC (QC-OFF と比較した QPS の増加) Fast-QC (QC-OFF と比較した QPS の増加)
1 5,099 6,467 (26.83%) 7,022 (37.71%)
8 28,782 28,651 (-0.46%) 45,017 (56.41%)
16 35,333 31,099 (-11.98%) 66,770 (88.97%)
32 34,864 27,610 (-20.81%) 67,623 (93.96%)
64 35,503 27,518 (-22.49%) 75,981 (114.01%)
128 35,744 27,733 (-22.41%) 80,396 (124.92%)
256 35,685 27,738 (-22.27%) 80,925 (126.78%)
512 35,308 27,398 (-22.40%) 79,323 (124.66%)
1,024 34,044 26,861 (-22.10%) 75,742 (122.48%)
高命中率
Fast Query Cache の QPS は同時実行数の増加とともに上昇を続け、QC-OFF を 124% 以上上回るピークに達します。一方、MySQL ネイティブのクエリキャッシュは、高い同時実行性で QC-OFF を 22% 下回るまで低下します。

低ヒット率の読み取りワークロード (約 10% のキャッシュヒット率、16 MB キャッシュ)

oltp_read_only スクリプトを使用します。16 MB のキャッシュはデータセットよりもはるかに小さいため、頻繁なエビクションが発生し、ヒット率は約 10% になります。

表 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 35,455 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 が最大 48% 低下します。一方、Fast Query Cache の QPS は QC-OFF の 1~4% 以内に留まり、キャッシュミスがほとんどの場合でも、実質的にオーバーヘッドは発生しません。

読み取りと書き込みが混在するワークロード

頻繁なテーブル更新によってキャッシュエントリが常に無効化される oltp_read_write スクリプトを使用します。

表 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%)
读写混合
Fast Query Cache を使用した場合、読み取りと書き込みが混在するワークロードにおいて QPS の低下は最大でも 2.17% にとどまります。増分無効化メカニズムにより、頻繁な書き込みが発生してもキャッシュメンテナンスのオーバーヘッドは低く抑えられています。

キャッシュのサイジング

query_cache_size は、ヒット率と QPS に直接影響します。以下のベンチマークは、10 GB のデータセット (テーブル数 100、各テーブルのレコード数 400,000、ホットデータ 20%、同時実行スレッド数 64、innodb_buffer_pool_size = 6 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 98,236 92% 169,412 (72.45%)

このテストから得られた主な知見は次のとおりです。

  • Fast Query Cache は、キャッシュサイズに関係なく、22% のヒット率であっても QPS が低下することはありません。

  • プライマリキークエリの場合、Fast Query Cache は、どのヒット率でも MySQL ネイティブのクエリキャッシュを上回り、場合によっては 90% 以上上回ります。

  • 範囲クエリおよび ORDER BY を含むクエリの場合、Fast Query Cache は、ヒット率が 90% 未満のときに MySQL ネイティブのクエリキャッシュよりも優れたパフォーマンスを発揮し、大幅な CPU リソースを節約します。

このテストの実際の結果セットサイズは 2.5 GB でした。ホットデータ (このテストでは 10 GB の 20% で 2 GB) をカバーするサイジングの場合、このシナリオで 80% 以上のヒット率に達するには、約 512 MB~1 GB の query_cache_size が必要になります。

重要

query_cache_size に過度のメモリを割り当てると、InnoDB バッファープールで利用可能なメモリが減少し、全体的なパフォーマンスが低下する可能性があります。query_cache_size を増やす場合は、必ず innodb_buffer_pool_size をその分だけ削減してください。

Fast Query Cache を使用する場合

Fast Query Cache の使用を推奨する場合

  • ワークロードが読み取り集中型で、書き込み頻度が低い場合 (例: eコマースサイトの商品詳細ページ、レポート用クエリ)

  • 読み取り/書き込み比率が高い特定のテーブルをキャッシュしたい場合。TABLE_STATISTICS テーブルを確認してこれらのテーブルを特定し、query_cache_type = 2 と組み合わせて SQL_CACHE キーワードを使用することで、対象のクエリのみをキャッシュします。TABLE_STATISTICS のクエリの詳細については、「Performance Insight」をご参照ください。

Fast Query Cache をグローバルに有効にする前に、InnoDB バッファープールのヒット率を確認してください。

SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';

ヒット率 = 1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)

InnoDB バッファープールのヒット率が 80% 未満の場合、バッファープールにはすでにメモリプレッシャーがかかっています。この状態で Fast Query Cache を有効にすると (innodb_buffer_pool_size を削減する必要があるため)、パフォーマンスが低下する可能性があります。キャッシュを有効にする前に、インスタンスメモリを増やすか、クエリを最適化してください。

Fast Query Cache を避けるべき場合

  • 書き込み負荷の高いワークロード: 頻繁な書き込みにより、キャッシュが常に無効化され、キャッシュの利点がほとんど得られないままオーバーヘッドが発生します。高頻度のトランザクションシステムでは、query_cache_type = 0 のままにしてください。

  • リアルタイムデータの要件: キャッシュされた結果は、実データより古い可能性があります。金融市場データのように古いデータの読み取りが許容されないユースケースでは、キャッシュを無効にするか、クエリごとに SQL_NO_CACHE を使用してください。

適切な query_cache_type 値の選択

query_cache_type はセッションレベルの変更をサポートしているため、グローバル設定を変更せずに、接続ごとにキャッシュ動作を調整できます。

SET SESSION query_cache_type = 1;  -- このセッションで有効化
SET SESSION query_cache_type = 0;  -- このセッションで無効化
動作 推奨される用途
0 Fast Query Cache をグローバルに無効化します。 書き込み負荷の高いワークロード、またはヒット率が非常に低いシナリオ。
1 条件を満たすすべてのクエリで有効化します。特定のステートメントをキャッシュ対象外にするには SQL_NO_CACHE を使用します。 データの変更が少なく、読み取り負荷の高いワークロード。
2 グローバルでは無効化します。SQL_CACHE を含むクエリのみをキャッシュします。 大規模なデータセット、予測不能なアクセスパターンがある場合、またはテーブルレベルでのキャッシュ制御が必要な場合。

次のステップ