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

PolarDB:SQL スロットリング

最終更新日:Nov 09, 2025

PolarDB for PostgreSQL は、SQL スロットリング機能を提供します。この機能を使用すると、エンドポイントに基づいてスロットリングルールを設定し、SQL 文からの異常トラフィックがビジネスに影響を与えるのを防ぐことができます。このトピックでは、SQL スロットリング機能の使用方法について説明します。

概要

SQL スロットリング機能を使用すると、エンドポイントに基づいてスロットリングルールを設定できます。SQL テンプレートを使用して現在のエンドポイントで実行される SQL 文を照合し、その最大同時実行数または 1 秒あたりのクエリ数 (QPS) を制限します。この機能は、次のシナリオで使用できます。

  • PolarDB クラスターに低速な SQL 文があり、データベースの負荷が高くなり、通常のビジネス運用に影響を与えています。

  • 特定タイプの高リスク SQL 文で利用可能なリソースを制限するか、その実行を完全に拒否したい場合。

手順

説明

SQL スロットリング機能を有効にするには、お問い合わせください。

  1. PolarDB コンソールにログインします。左側のナビゲーションウィンドウで、[クラスターリスト] をクリックします。クラスターが配置されているリージョンを選択します。対象クラスターの ID をクリックして、クラスター詳細ページを開きます。

  2. 左側のナビゲーションウィンドウで、[設定と管理] > [セキュリティ管理] を選択します。

  3. [SQL スロットリング] タブで、[追加] をクリックして SQL スロットリングルールを作成します。

    image

  4. [SQL スロットリングルールの作成] ダイアログボックスで、次のパラメーターを設定し、[OK] をクリックします。

    セクション

    パラメーター

    説明

    基本情報

    ルール名

    スロットリングルールの名前。次の要件を満たす必要があります。

    • 最大 30 文字までです。

    • 大文字、小文字、数字で構成する必要があります。

    ルールの説明

    オプション。スロットリングルールの説明。これは将来の管理に役立ちます。説明は最大 64 文字までです。

    エンドポイント ID

    スロットリングルールを適用するエンドポイントを選択します。

    説明
    • 現在、スロットリングルールは、アクティブなリクエストに基づく負荷分散を使用するクラスターエンドポイントおよびカスタムエンドポイントでのみ設定できます。これらのエンドポイントは、読み取り/書き込みまたは読み取り専用にすることができます。プライマリエンドポイントおよび接続に基づく負荷分散を使用する読み取り専用エンドポイントは、SQL スロットリングをサポートしていません。

    • 異なるエンドポイントで設定されたスロットリングルールは、互いに影響しません。同じエンドポイントで設定されたスロットリングルールは、そのエンドポイントを使用するビジネス接続にのみ適用されます。

    ルール設定

    ルールタイプ

    スロットリングルールモードを選択します。有効な値は [アクティブな同時実行ステートメントのスロットリング][接続ごとの QPS のスロットリング] です。

    説明

    接続ごとの QPS のスロットリングは、単一接続の 1 秒あたりのリクエスト数を制限します。このモードは、ビジネス側が接続プールを持っているか、持続的接続を使用するシナリオで使用できます。短命な接続のシナリオでは、アクティブな同時実行ステートメントのスロットリングを使用することをお勧めします。

    現在のモード

    SQL テンプレートの照合モードを選択します。有効な値は [テンプレート一致][全文一致] です。2 つの照合モードの違いの詳細については、「テンプレート照合と全文照合」をご参照ください。

    データベースアカウント名

    スロットリングルールを適用するデータベースアカウントを指定します。最大 10 個のアカウントを指定できます。複数のアカウント名はカンマ (,) で区切ります。このパラメーターを空のままにすると、ルールはデフォルトですべてのアカウントに適用されます。

    データベース名

    スロットリングルールを適用するデータベースを指定します。最大 10 個のデータベースを指定できます。複数のデータベース名はカンマ (,) で区切ります。このパラメーターを空のままにすると、ルールはデフォルトですべてのデータベースに適用されます。

    SQL テンプレート

    SQL テンプレートを設定します。詳細については、「SQL テンプレートと照合モード」をご参照ください。

    最大待機キュー長

    待機キューの最大長を設定します。値は 0 から 1024 の範囲である必要があります。一致する SQL 文の同時実行数または QPS がルールの上限に達すると、その文は再試行のために遅延キューに入ります。遅延キュー内の SQL 文の数が最大長を超えると、新しいリクエストは直接エラーを返します。適切な最大待機キュー長を設定することで、多くの SQL 文がスロットリングされたときに遅延キューが無限に増大するのを防ぐことができます。これにより、データベースプロキシでのメモリ不足 (OOM) エラーを回避できます。

    最大アクティブ同時実行ステートメント数

    アクティブな同時実行ステートメントの最大数を設定します。

    説明

    このパラメーターは、[ルールタイプ] パラメーターが アクティブな同時実行ステートメントのスロットリング に設定されている場合にのみ必要です。

    接続ごとの最大 QPS

    各接続の最大 QPS を設定します。

    説明

    このパラメーターは、[ルールタイプ] パラメーターが 接続ごとの QPS のスロットリング に設定されている場合にのみ必要です。

仕組み

SQL スロットリングは、データベースプロキシに実装された機能です。データベースプロキシでスロットリングルールを設定して、特定の転送 SQL 文の同時実行数または QPS を制御します。これは、データベースクラスターの読み取り/書き込みノードまたは読み取り専用ノードには影響しません。したがって、この機能はクラスターエンドポイントまたはカスタムエンドポイントに対してのみ設定できます。

SQL テンプレートと照合モード

テンプレート照合と全文照合

SQL テンプレートは、PolarDB for PostgreSQL または クラスターの標準構文に従う任意の SQL 文にすることができます。SQL テンプレートを設定すると、データベースプロキシは選択した照合モードに基づいてそれを前処理します。

  • 次の SQL テンプレートでスロットリングルールを設定するとします。

    SELECT * FROM tbl WHERE id < 1;
    • テンプレート照合を選択した場合、SQL テンプレートは正規化されます。余分なスペースやコメントは削除されます。単一引用符で囲まれた文字列や数値など、SQL 文の定数部分はワイルドカード文字に置き換えられます。結果は次のようになります。

      -- テンプレート結果
      SELECT * FROM tbl WHERE id < ?
    • 全文照合を選択した場合、SQL テンプレートも正規化されます。ただし、定数部分は置き換えられません。結果は次のようになります。

      -- フォーマットされた結果のみ
      SELECT * FROM tbl WHERE id < 1

    その後、データベースプロキシは、後続の照合のために、フォーマットされた SQL 文の一意の識別子を生成します。

  • スロットリングルールが有効になると、データベースプロキシは、SQL テンプレートと同様の方法で、すべてのビジネス SQL 文も前処理します。次のビジネス SQL 文を例にとります。

    SELECT * FROM tbl WHERE id < 100;

    2 つのフォーマットされた SQL 文も生成され、一意の識別子が計算され、スロットリングルールとの照合が試みられます。

    -- テンプレート結果
    SELECT * FROM tbl WHERE id < ?
    
    -- フォーマットされた結果のみ
    SELECT * FROM tbl WHERE id < 100

SQL スロットリングルールを有効にすると、データベースプロキシは現在の SQL 文を転送する前に、現在設定されているスロットリングルールを走査します。スロットリングルールがテンプレート照合用に設定されている場合、テンプレート化された結果がルールの SQL テンプレートとの照合に使用されます。スロットリングルールが全文照合用に設定されている場合、フォーマットされた結果がルールの SQL テンプレートとの照合に使用されます。一致がヒットすると、同時実行数または QPS が記録され、対応するスロットリング操作が実行されます。

したがって、前の例のビジネス SQL 文と SQL テンプレートでは、テンプレート照合が設定されている場合にのみルールがヒットします。

パラメーター化のサポート

SQL テンプレートは、PostgreSQL の標準的なパラメーターバインディング構文と一致するパラメーター化構文を許可します。

SELECT * FROM tbl WHERE id < $1 AND name = $2 LIMIT 1;

パラメーター化された部分は、テンプレート照合と全文照合の両方でワイルドカード文字としてフォーマットされます。

-- テンプレート結果
SELECT * FROM tbl WHERE id < ? AND name = ? limit ?

-- フォーマットされた結果のみ
SELECT * FROM tbl WHERE id < ? AND name = ? limit 1

したがって、次のビジネス SQL 文の場合:

SELECT * FROM tbl WHERE id < $1 AND name = 2 LIMIT 100;

現在のモードがテンプレート照合に設定されている場合、前のルールがヒットする可能性があります。現在のモードが全文照合に設定されている場合、前のルールはヒットしません。

説明

SQL テンプレートで直接パラメーター化に ? 記号を使用することはできません。

-- これは無効な SQL テンプレートです。標準の PostgreSQL 構文に従っておらず、どの SQL 文とも一致しません。
SELECT ?, ?, ?;

-- これは有効な SQL テンプレートです。
SELECT $1, $2, $3;

プリペアドステートメント

ビジネスでプリペアドステートメントを使用する場合、PREPARE 文自体はスロットリングをトリガーしません。EXECUTE 文のみがスロットリングをトリガーします。EXECUTE 文の場合、対応する PREPARE 文の SQL 部分がフォーマットまたはテンプレート化されて、ルールに一致します。

説明

プリペアドステートメントの詳細については、「PREPARE」をご参照ください。

次の SQL テンプレートを使用してスロットリングルールを設定します。照合モードとしてテンプレート照合を選択します。

SELECT * FROM tbl WHERE id < $1 AND name > $2;

次のビジネス SQL 文の場合:

-- PREPARE 文はスロットリングをトリガーしません。
PREPARE s1 AS SELECT * FROM tbl WHERE id < $1 AND name > 100;

-- EXECUTE 文は、対応する PREPARE 文の SQL 部分を使用してスロットリングルールに一致させます。
EXECUTE s1;

EXECUTE s1;

EXECUTE s1;

3 つの EXECUTE 文はスロットリングルールにヒットし、スロットリングされます。

同様に、スロットリングルールの SQL テンプレートで PREPARE 文を使用する場合、PREPARE 文内の SQL 部分のみがスロットリングのためにフォーマットまたはテンプレート化されます。したがって、ルールを作成する際、次の 2 つの SQL テンプレートは同等です。

-- テンプレート 1
PREPARE s1 AS SELECT * FROM tbl WHERE id < $1 AND name > $2;

-- テンプレート 2
SELECT * FROM tbl WHERE id < $1 AND name > $2;

拡張プロトコルのサポート

プリペアドステートメントと同様に、ビジネスドライバーが拡張プロトコルを使用する場合、Execute メッセージのみがスロットリングをトリガーします。各 Execute メッセージに対して、データベースプロキシは対応する Parse メッセージを見つけ、SQL テンプレートを計算してスロットリングルールに一致させます。したがって、SQL スロットリングは拡張プロトコルをサポートします。ビジネスが使用するプロトコルについて心配する必要はありません。

説明

拡張プロトコルの詳細については、「PostgreSQL ドキュメント」をご参照ください。

制限事項

SQL スロットリング機能には次の制限があります。

  • 複数文 SQL はスロットリングでサポートされていません。複数文 SQL を使用すると、設定されたスロットリングルールはトリガーされません。

    複数文 SQL とは、セミコロンで区切られた複数の SQL 文を含む単一の SQL テキストを指します。以下は、Java Database Connectivity (JDBC) ドライバーを使用した複数文実行の例です。

    Statement statement = connection.createStatement();
    
    statement.execute("select 1; select 2; select 3");

    複数文の実行は、同時に複数のスロットリングルールにヒットする可能性があります。予期しない結果を避けるため、スロットリングはサポートされていません。

  • トランザクション制御文やストアドプロシージャなどの一部の特殊な文は、スロットリングでサポートされていません。COMMIT などのトランザクション制御文をスロットリングすると、トランザクションが正常に終了しなくなる可能性があります。したがって、これらの文はスロットリングルールにヒットしません。

  • クライアントまたはドライバーがステートメントバッチモードを使用する場合、バッチ処理された SQL 文に対してヒットした最初のスロットリングルールのみがトリガーされます。以下は、JDBC ドライバーを使用したバッチ実行の例です。

    Statement statement = connection.createStatement();
    
    statement.addBatch("select 1");
    statement.addBatch("select 2");
    statement.addBatch("select 3");
    
    int[] result = statement.executeBatch();
    statement.close();
    connection.close();

    複数文の実行と同様に、ステートメントバッチを使用する場合、ドライバーは通常、複数の SQL 文の拡張プロトコルメッセージを組み合わせて一度に送信します。これにより、複数のスロットリングルールが同時にヒットする状況が発生する可能性もあります。この場合、ヒットした最初のスロットリングルールのみが有効になります。バッチ実行の例では、次の 3 つの SQL テンプレートのスロットリングルールがエンドポイントで同時に設定されている場合:

    -- テンプレート 1
    SELECT 1;
    
    -- テンプレート 2
    SELECT 2;
    
    --テンプレート 3
    SELECT 3;

    テンプレート 1 のみがヒットします。

  • SQL テンプレートでは、大文字と小文字を区別しないキーワードはサポートされていません。スロットリングしたい SQL テキストの大文字と小文字に一致するように SQL テンプレートを設定する必要があります。

  • SQL テンプレートは、要素の数を無視する `in` や `any` などの可変長式のテンプレート化をサポートしていません。例:

    -- SQL テンプレート
    SELECT * FROM tbl WHERE id IN ($1, $2, $3);
    
    -- SQL1、テンプレートにヒット可能
    SELECT * FROM tbl WHERE id IN (1, 6, 8);
    
    -- SQL2、テンプレートにヒット不可
    SELECT * FROM tbl WHERE id IN (1, 6, 8, 8);
  • スロットリングルールが設定されていない場合、新しく追加されたルールは既存の接続には適用されません。コンソールにスロットリングルールが存在する場合、それが有効かどうかにかかわらず、後続の追加、変更、または削除操作はすべての接続にリアルタイムで適用されます。

    説明
    • ビジネスで持続的接続を使用し、新しいルールをいつでもすぐに有効にしたい場合は、対応するエンドポイントに任意のルールを設定し、それを無効にして保持することをお勧めします。これにより、後続のルールの追加や変更が、新規および既存の両方の接続に適用されるようになります。

    • データベースプロキシのバージョンが 2.3.58 以降の場合、スロットリングルールの追加、変更、または削除はすべての接続にリアルタイムで適用されます。コンソールで データベースプロキシのバージョンを表示できます。マイナーエンジンバージョンが要件を満たしていない場合は、データベースプロキシのバージョンをアップグレードできます。

スロットリング方法

現在、SQL スロットリングは SQL テンプレートと遅延キューを使用して、QPS またはアクティブな同時実行のスロットリングを実装します。ビジネス SQL 文は、対応するルールの QPS または同時実行数が記録される前に、スロットリングルールにヒットする必要があります。同時実行数または QPS がルールで設定された制限を超えると、データベースプロキシは SQL 文を遅延キューに配置します。一定期間後、プロキシはその文を再試行します。これにより、データベース側の同時実行数または QPS がルールの上限を超えないレベルに維持されます。

遅延キューの遅延時間は、ルールで設定された QPS または同時実行数に反比例します。ルールにヒットして遅延キューで待機できる SQL 文の最大数は、ルールで設定された最大待機キュー長によって制限されます。制限を超えると、プロキシは SQL 文を転送しません。代わりに、次のエラーをクライアントに返します。

SELECT 123;
Current query is being throttled and waiting queue is full.
説明

上記のエラーは、現在の接続のトランザクション解決を中断または変更しません。クライアントがこのエラーを受け取った後でも、トランザクションをコミットまたはロールバックすることを選択できます。

さらに、設定された SQL スロットリングルールで最大アクティブ同時実行数または接続ごとの最大 QPS が 0 の場合、ルールにヒットした SQL 文は転送が拒否されます。上記のエラーが直接クライアントに返されます。この方法を使用して、あるクラスの SQL 文の実行を完全に拒否できます。

説明
  • 遅延キューには最小再試行間隔があります。設定された最大 QPS が大きい場合、実際の QPS は設定値よりわずかに低くなる可能性があります。

  • 高可用性 (HA) のため、データベースプロキシは通常 2 つ以上のノードにデプロイされます。クライアント接続はこれらのノードにランダムに割り当てられます。[最大アクティブ同時実行ステートメント数][最大待機キュー長] はノードレベルで設定されます。各ノードは、その同時実行数とキュー長を独立してカウントします。したがって、実際の合計同時実行数を正確に制御することはできません。ノード数を N、単一ノードで最大アクティブ同時実行ステートメント数に C、最大待機キュー長に Q が設定されていると仮定します。クライアントの同時実行数の範囲は [C+Q, N × (C+Q)] です。データベースのアクティブな同時実行数の範囲は [C, N × C] です。

  • SQL スロットリングルールを設定すると、プロキシは各ビジネス SQL 文に対して、その文がルールにヒットするかどうかにかかわらず、いくつかの操作を実行します。これらの操作には、テンプレート化、一意の識別子の生成、およびルールとの照合試行が含まれます。SQL スロットリングを有効にすると、転送パフォーマンスが 5% から 10% 低下する可能性があります。SQL スロットリングは、データベース側の低速 SQL 文が通常のビジネス運用に影響を与える場合にのみ使用してください。低速 SQL 文の問題が解決したら、コンソールでスロットリングルールを無効にできます。無効化されたルールは有効になりませんが、保存されます。いつでも有効にできます。

ベストプラクティス

設定されたスロットリングルールが有効かどうかをテストする

スロットリングルールを適用するアカウントとデータベースを設定できるため、新しいアカウントを作成し、同時実行数または QPS を 0 に設定したスロットリングルールを設定できます。これにより、ルールがスロットリングしたい SQL 文にヒットするかどうかをテストできます。

次の SQL 文をスロットリングするとします。

SELECT * FROM generate_series(1, 100000);
  1. テストデータベースアカウントを作成する

    image

  2. テストアカウントのスロットリングルールを設定し、最大アクティブ同時実行数を 0 に設定します。スロットリングルールの設定方法の詳細については、「手順」をご参照ください。

    image

  3. ルールが有効であることを確認します。現在のルールは新しく作成されたテストアカウントにのみ適用され、現在のビジネスには影響しません。ルールを設定した後、ルールで選択したエンドポイントを介してデータベースに接続し、SQL 文を実行します。期待どおりにエラーが返された場合、ルールは有効になっています。

    SELECT * FROM generate_series(1, 100000);
    Current query is being throttled and waiting queue is full.

本番環境で低速 SQL 文を処理するために SQL スロットリングを使用する

  1. テスト環境を準備します。

  2. ECS インスタンスで、pgbench ツールを使用して PolarDB クラスターエンドポイントに接続し、ストレステストデータを初期化します。

    pgbench -h <PolarDB_cluster_endpoint> -p <Port_of_the_PolarDB_cluster_endpoint> -i -s 10 -U <Username_of_the_PolarDB_database_account> <Name_of_the_test_database>

    次に、ストレステストを開始します。pgbench の組み込み TPC-B ライクモードを使用して、通常のビジネス負荷をシミュレートします。

    pgbench -h <PolarDB_cluster_endpoint> -p <Port_of_the_PolarDB_cluster_endpoint> -P 1 -b tpcb-like -j 5 -c 10 -M prepared -T 6000 -U <Username_of_the_PolarDB_database_account> <Name_of_the_test_database> 
  3. 低速 SQL 文のシナリオをシミュレートします。新しい接続セッションを作成し、テストデータベースで次の文を実行します。

    WITH t AS (SELECT md5(i::text) AS id FROM generate_series(1, 10000000) i) SELECT * FROM t ORDER BY id LIMIT 1;

    この SQL 文は大量の計算リソースを消費します。通常、次の結果が返されるまでに約 5 秒かかります。

                    id                
    ----------------------------------
     0000023f507999464aa2b78875b7e5d6
    (1 row)

    再度 pgbench を開始します。カスタムスクリプトを使用して、上記の SQL 文でストレステストを実行します。10 個の接続を開始して、低速 SQL 文がクラスターの高負荷を引き起こすシナリオをシミュレートします。

    echo "WITH t AS (SELECT md5(i::text) AS id FROM generate_series(1, 10000000) i) SELECT * FROM t ORDER BY id LIMIT 1;" > slow.sql
    
    pgbench -h <PolarDB_cluster_endpoint> -p <Port_of_the_PolarDB_cluster_endpoint> -P 1 -f slow.sql -j 5 -c 10 -M prepared -T 6000 -U <Username_of_the_PolarDB_database_account> <Name_of_the_test_database> 

    ストレステストが開始されると、通常のビジネス負荷はすぐに急激に低下します。

    image

  4. コンソールで、次の SQL テンプレートを使用してスロットリングルールを設定します。[ルールタイプ] を アクティブな同時実行ステートメントのスロットリング に設定します。

    WITH t AS (SELECT md5(i::text) AS id FROM generate_series($1, $2) i) SELECT * FROM t ORDER BY id LIMIT $3;

    image

    低速 SQL 文の同時実行数を 1 に制限します。ルールを有効にすると、ビジネス負荷が増加することがわかります。これは、スロットリングルールが有効になったことを示します。

    image

  5. コンソールで、スロットリングルールを変更します。対象のスロットリングルールの行で、[操作] 列の [変更] をクリックします。最大アクティブ同時実行数を 0 に設定して、低速 SQL 文の実行を完全に拒否します。

    image

    ルールを設定すると、低速 SQL 文のストレステストがエラーを返して中断されることがわかります。この時点で、ビジネス負荷は完全に回復します。

    image