AnalyticDB for MySQL は、LIMIT、OFFSET、および ORDER BY 句を含む大規模なページングクエリを高速化し、ディープページネーションによって引き起こされるパフォーマンスの低下を解決するキャッシュ機能を提供します。このトピックでは、ページングキャッシュ機能を使用してページングクエリのパフォーマンスを最適化する方法と、代替アプローチであるキーセットページネーションについて説明します。
前提条件
V3.2.3 以降の AnalyticDB for MySQL クラスターが作成されていること。
-
AnalyticDB for MySQLのマイナーバージョンを照会するには
-
AnalyticDB For MySQL Data Warehouse Editionクラスターのマイナーバージョンを表示および更新する方法については、「クラスターのマイナーバージョンの更新」をご参照ください。
概要
深いページングクエリによって引き起こされるパフォーマンスの問題を解決するため、AnalyticDB for MySQL はページングキャッシュ機能を提供します。ページングクエリを初めて開始すると、システムはデータベースからデータをクエリし、クエリ結果を一時キャッシュテーブルに保存します。同じ SQL パターンを共有する後続のページングクエリでは、システムが一時キャッシュテーブルからデータを読み取ることで、繰り返し行われるソート操作を防ぎます。これにより、深いページングクエリによるパフォーマンスの問題が効果的に解決され、ORDER BY 句が原因で発生する OOM エラーも防止されます。AnalyticDB for MySQL は、リソースを適切に利用するため、削除ポリシーに基づいて不要になったキャッシュデータを自動的にクリアします。
ページングキャッシュ機能は、次のシナリオに適しています。
使用方法
キャッシュデータベースの設定
ページングキャッシュ機能を使用してクエリ結果をキャッシュする前に、ページングクエリ用の一時キャッシュテーブルを格納するデータベースを指定することを推奨します。データベースを指定しない場合、一時キャッシュテーブルは接続されている内部データベースに格納されます。ページングキャッシュ機能を有効にすると、一時キャッシュテーブルが自動的に作成されます。
外部データベースをキャッシュデータベースとして指定することはできません。
たとえば、paging_cache データベースをキャッシュデータベースとして指定できます。他のデータベースを指定することもできます。
SET ADB_CONFIG PAGING_CACHE_SCHEMA=paging_cache;
ページングクエリに対するページングキャッシュ機能の有効化
複数のページングクエリが同じ SQL パターンを共有する場合、SQL ステートメントにヒントを追加してパフォーマンスを向上させることができます。ヒントを含むページングクエリを初めて開始すると、システムはページングクエリの結果を格納するための一時キャッシュテーブルを作成します。同じ SQL パターンを共有する後続のページングクエリを開始する際に、同じヒントを SQL ステートメントに追加できます。これにより、システムはデータベースへの繰り返しアクセスを必要とせず、一時キャッシュテーブルからデータを読み取ります。
制限事項
LIMIT 句と OFFSET 句を削除した後、ページングクエリを実行したいデータエントリの数は 1 億未満でなければなりません。
クエリ対象のデータエントリ数が 1 億を超える場合は、 チケットを起票 してデータエントリ数の上限を調整してください。
ページングキャッシュ機能を有効化する方法
次のいずれかのヒントを使用して、ページングキャッシュ機能を有効にできます。
-
paging_id=<paging_id>paging_idパラメーターは、同じ SQL パターンを共有するがLIMIT句とOFFSET句の値が異なる一連のページングクエリに対して作成されるキャッシュテーブルを指定します。クライアントは、一連のページングクエリのキャッシュテーブルを一意に識別するために、一意の ID を生成する必要があります。-
指定された
paging_idパラメーターが存在しない場合、キャッシュテーブルが作成されます。 -
クエリで指定された
paging_idパラメーターが存在し、クエリに含まれる SQL パターンがpaging_idパラメーターに対応する SQL パターンと一致する場合、クエリはキャッシュにヒットします。 -
クエリで指定された
paging_idパラメーターが存在するが、クエリに含まれる SQL パターンがpaging_idパラメーターに対応する SQL パターンと一致しない場合、エラーが発生します。paging_idパラメーターがすでに使用されているかどうかを確認できます。詳細については、本トピックの「キャッシュテーブルに関する情報のクエリ」セクションをご参照ください。
説明paging_idパラメーターは、次の命名規則を満たす必要があります:パラメーター名は 1~127 文字の長さで、文字、数字、アンダースコア (_) を使用できます。パラメーター名は文字またはアンダースコア (_) で始まる必要があります。パラメーター名には、シングルクォーテーション (')、ダブルクォーテーション (")、感嘆符 (!)、またはスペースを含めることはできません。パラメーター名を SQL の 予約語 にすることはできません。たとえば、ページングキャッシュ機能を使用する一連のページングクエリの結果に対して、ページング ID を
paging123に設定できます。/*paging_id=paging123*/ SELECT * FROM t_order ORDER BY id LIMIT 0, 100; -
-
paging_cache_enabled=trueこの方法では、ヒントを頻繁に変更する必要はありません。サーバーは
LIMIT句とOFFSET句を削除した SQL パターンを使用してページング ID を生成し、一連のページングクエリを識別します。SQL パターンマッチングへの依存は、この方法の柔軟性を制限します。LIMIT 句と OFFSET 句を除いて同じ SQL パターンを共有するページングクエリに対してキャッシュテーブルが存在しない場合、キャッシュテーブルが作成されます。LIMIT 句と OFFSET 句を除いて同じ SQL パターンを共有するページングクエリに対してキャッシュテーブルが存在する場合、そのキャッシュテーブルがデータのクエリに使用されます。
ステートメントの例:
/*paging_cache_enabled=true*/ SELECT * FROM t_order ORDER BY id LIMIT 0, 100;
キャッシュテーブルの作成に失敗した場合は、ページングクエリのキャッシュデータをクリアし、ページングクエリを再実行してキャッシュテーブルを作成する必要があります。
キャッシュテーブルに関する情報のクエリ
現在のクラスター内のすべてのページングクエリのキャッシュテーブルに関する情報 (ページング ID、キャッシュサイズ、キャッシュステータスなど) をクエリできます。
SELECT * FROM INFORMATION_SCHEMA.KEPLER_PAGING_CACHE_STATUS_MERGED;
キャッシュテーブルの最大数の指定
現在のクラスター内のキャッシュテーブルの最大数を指定できます。デフォルト値: 32。
SET ADB_CONFIG PAGING_CACHE_MAX_TABLE_COUNT=32;
キャッシュテーブルの総数が上限を超えているときにキャッシュテーブルを作成しようとすると、エラーが発生します。エラーメッセージの例:
Paging cache count exceeds the limit. Please clean up unused caches or increase the related parameter using SET ADB_CONFIG PAGING_CACHE_MAX_TABLE_COUNT=xxx.
エラーメッセージに基づいて、不要になったキャッシュデータをクリアするか、キャッシュテーブルの最大数を増やしてください。
キャッシュテーブルの有効期間の指定
キャッシュテーブルの有効期間を指定できます。単位:秒。有効期間が終了すると、キャッシュテーブルは無効になります。同じ SQL パターンを共有する後続のページングクエリを開始すると、システムはデータベースにアクセスし、キャッシュテーブルを更新します。ほとんどの場合、レポートの同時実行制御シナリオでキャッシュテーブルの有効期間を指定できます。
たとえば、/*paging_cache_enabled=true, paging_cache_validity_interval=300*/ ヒントを使用して、キャッシュテーブルが作成後 300 秒間有効になるように設定できます。ステートメントの例:
/*paging_cache_enabled=true, paging_cache_validity_interval=300*/ SELECT * FROM t_order ORDER BY id LIMIT 0, 100;
ページングクエリのキャッシュデータのクリア
ページングキャッシュ機能を使用してページングされたクエリ結果をキャッシュする場合、キャッシュデータは AnalyticDB for MySQL のホットストレージ領域にキャッシュされます。特定のキャッシュデータが不要になった場合は、キャッシュデータをクリアして、使用可能なストレージを増やすことができます。
手動クリア
-
SQL パターンで指定されたページングクエリのキャッシュデータ
/*paging_cache_enabled=true, invalidate_paging_cache=true*/ヒントを使用して、SQL パターンで指定されたページングクエリのキャッシュデータをクリアします。ステートメントの例:
/*paging_cache_enabled=true,invalidate_paging_cache=true*/ SELECT * FROM t_order ORDER BY id LIMIT 0, 100; -
paging_idパラメーターで指定されたページングクエリのキャッシュデータpaging_idパラメーターで指定されたページングクエリのキャッシュデータをクリアします。ステートメントの例:
CLEAN_PAGING_CACHE paging123;説明paging_idパラメーターの値を取得する方法については、本トピックの「キャッシュテーブルに関する情報のクエリ」セクションをご参照ください。
自動クリア
キャッシュの有効期限を指定して、指定された時間範囲内にアクセスされなかったページングクエリのキャッシュデータをクリアできます。デフォルト値: 3600。単位:秒。デフォルトでは、1 時間以内にアクセスされなかったキャッシュデータは自動的にクリアされます。
SET ADB_CONFIG PAGING_CACHE_EXPIRATION_TIME=3600;
代替策:キーセットページネーション
ビジネスシナリオがカーソルベースのナビゲーション (たとえば、任意のページにジャンプするのではなく、次のページや前のページに移動する) をサポートしている場合、従来の OFFSET ベースのページネーションの代替としてキーセットページネーションを使用できます。OFFSET を使用して行をスキップする代わりに、キーセットページネーションは WHERE 句を使用して、最後に取得した値に基づいて行をフィルター処理します。これにより、ディープページにおけるグローバルソートとノード間のデータシャッフルのオーバーヘッドを回避できます。
たとえば、id 列が主キーであり、現在のページの最後の id の値が 1000 であると仮定します。次の SQL ステートメントを使用して、次のページをクエリします。
-- 従来のディープページネーション (低速)
SELECT * FROM t_order ORDER BY id LIMIT 1000, 100;
-- キーセットページネーション (高速、推奨)
SELECT * FROM t_order WHERE id > 1000 ORDER BY id LIMIT 100;
キーセットページネーション方式では、多数の行をソートしたりスキップしたりすることなく、インデックスから直接次の行のバッチのみを取得します。これにより、ディープページネーションによって引き起こされるパフォーマンスの低下が解消されます。クエリのパフォーマンスは、ページネーションの深さに関係なく一定に保たれます。
一般的なエラーとトラブルシューティング
Paging cache prepare failed, and cache is not available
エラーメッセージ:
Paging cache prepare failed, and cache is not available. Please use /*paging_cache_enabled=true,invalidate_paging_cache=true*/ to clean the unavailable cache or set a specific pagingId with /*paging_id=xxx*/ to gen a new cache. Note that the old and new cache data may be inconsistent.
原因:ページングキャッシュ機能を使用してデータをクエリする際、ノードの再起動やスケーリングなどの例外が発生することがあります。ページングクエリが作成に失敗したキャッシュテーブルにヒットした場合、サーバーはデータベースにアクセスせず、キャッシュテーブルを自動的に再作成しません。サーバーはエラーをスローします。
解決策:データの整合性を確保するために、次の操作を実行することを推奨します。データ書き出しシナリオでは、書き出したデータと利用できないキャッシュデータをクリアしてから、ページングクエリを再実行してキャッシュテーブルを再作成することを推奨します。他のシナリオでは、利用できないキャッシュデータをクリアするか、paging_id パラメーターに新しい値を指定してから、ページングクエリを再実行してキャッシュテーブルを再作成することを推奨します。
パフォーマンス比較
100 GB の TPC-H データセットを使用して、データ書き出しシナリオにおけるページングクエリに対するページングキャッシュ機能の最適化効果を評価します。
このテストでは、100 万エントリの書き出しデータが含まれます。各ページには 10 万エントリが含まれます。次のステートメントを実行して、最初のページに対してページングクエリを実行します。
-- ページングキャッシュ機能を使用しない一般的なページングクエリ
SELECT * FROM lineitem ORDER BY l_orderkey,l_linenumber LIMIT 0,100000;
-- ページングキャッシュ機能を使用したページングクエリ (データ書き出しシナリオでは ORDER BY を削除)
/*paging_cache_enabled=true*/ SELECT * FROM lineitem LIMIT 0,100000;
テスト結果:
クエリリクエストは単一同時実行モードで実行されます。データ書き出しプロセス中、一般的なページングクエリの平均応答時間は 54,391 ms です。ページングキャッシュ機能を有効にすると、平均応答時間は 525 ms になります。パフォーマンスは約 103 倍向上します。CPU 使用率とメモリ使用量は大幅に減少します。
ページングキャッシュ機能は、データ書き出しプロセス中のページングクエリの応答時間を大幅に短縮し、CPU およびメモリリソースの消費を効果的に削減します。
