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

PolarDB:ステートメントキュー

最終更新日:Mar 29, 2026

多数のデータ操作言語(DML)ステートメントが同時に同一行を対象とする場合、InnoDB の行レベルロックにより、これらのステートメントは直列化されます。同時実行数が増加すると、スレッドがロックの後ろでキューに並び、スループットが低下します。ステートメントキューは、ハッシュアルゴリズムを用いて競合するステートメントを共有バケットにルーティングすることで、ロック獲得の競合を回避し、代わりにキュー内で待機させる仕組みです。これにより、ロックの取得および解放を繰り返すオーバーヘッドが低減されます。

単一行に対して 128 スレッドの同時 UPDATE ステートメントを実行するベンチマークテストにおいて、ステートメントキューを有効化した PolarDB は、標準的な MySQL と比較して約 4 倍のスループットを達成します。

ステートメントキューの適用範囲

ステートメントキューは、大量の DML ステートメントが同一の行を対象とするワークロードで最も効果的です。たとえば、リーダーボードのカウンター、在庫更新、または多数の同時書き込みが同一のプライマリキーに集中するチケット予約システムなどが該当します。

一方、ステートメントが異なる行を対象とするワークロードでは、ロック競合が少ないため、効果は限定的です。

hotspot 変数を ON に設定してホットローオプティマイゼーションを有効化している場合、ステートメントキューは自動的にバイパスされます。両機能を併用することはできませんので、どちらか一方のみをご利用ください。

前提条件

開始する前に、以下の条件を満たしていることを確認してください。

  • 以下のマイナーエンジンバージョンのいずれかを実行中の PolarDB for MySQL クラスター:

    • PolarDB for MySQL 8.0:マイナーエンジンバージョン 8.0.1.1.10 以降

    • PolarDB for MySQL 5.7:マイナーエンジンバージョン 5.7.1.0.6 以降

    • PolarDB for MySQL 5.6:マイナーエンジンバージョン 20200601 以降

構文

PolarDB for MySQL 5.6

POLARDB_STATEMENT_CONCURRENT_QUEUE キーワードを、DML キーワード(SELECTUPDATEINSERT、または DELETE)の直後に配置します。このキーワードは、4 つの DML 文の種類すべてに適用されます。

値によるキューイング

明示的な整数または文字列の値に基づいて、ステートメントをバケットに割り当てます。同じ値を持つステートメントは同一のバケットに配置されます。

構文:

POLARDB_STATEMENT_CONCURRENT_QUEUE [int | string]

例:

INSERT POLARDB_STATEMENT_CONCURRENT_QUEUE 1 INTO t VALUES(1, 1, 'xpchild');
UPDATE POLARDB_STATEMENT_CONCURRENT_QUEUE 1 t SET c=c+1 WHERE id = 1;
UPDATE POLARDB_STATEMENT_CONCURRENT_QUEUE "xpchild" t SET col1 = col1+1 WHERE id = 1;

WHERE 句のフィールドによるキューイング

WHERE 句に含まれる列の実行時値に基づいて、ステートメントをバケットに割り当てます。同一のフィールド値を持つステートメントは同一のバケットに配置されます。

構文:

POLARDB_STATEMENT_CONCURRENT_QUEUE [field]

例:

SELECT POLARDB_STATEMENT_CONCURRENT_QUEUE id * FROM t WHERE 3 = id;
UPDATE POLARDB_STATEMENT_CONCURRENT_QUEUE id t SET c=c+1 WHERE id = 1 AND name = 'xpchild';
WHERE 句では、元の列に対する二項演算のみをサポートします。各二項演算の右辺には、リテラルの数値または文字列を指定する必要があります。元の列に対する関数呼び出しや計算式はサポートされていません。

PolarDB for MySQL 5.7 および 8.0

ヒント構文 /*+ ... */ を DML キーワード(SELECTUPDATEINSERT、または DELETE)の直後に配置します。このヒントは、4 つの DML 文の種類すべてに適用されます。

値によるキューイング

構文:

/*+ CCL_QUEUE_VALUE([INT | STRING]) */

例:

UPDATE /*+ ccl_queue_value(1) */ t SET c=c+1 WHERE id = 1;
UPDATE /*+ ccl_queue_value('xpchild') */ t SET c=c+1 WHERE name = 'xpchild';

WHERE 句のフィールドによるキューイング

構文:

/*+ CCL_QUEUE_FIELD(STRING) */

例:

UPDATE /*+ ccl_queue_field("id") */ t SET c=c+1 WHERE id = 1 AND name = 'xpchild';
WHERE 句では、元の列に対する二項演算のみをサポートします。各二項演算の右辺には、リテラルの数値または文字列を指定する必要があります。元の列に対する関数呼び出しや計算式はサポートされていません。

キューのサイズの設定

キューの容量を制御する変数が 2 つあります。ご使用の同時実行数に応じて、適切な値を設定してください。

変数説明有効な値デフォルト値
ccl_queue_bucket_countバケット数1~644
ccl_queue_bucket_sizeバケットあたりの最大同時実行ステートメント数1~409664

キューの状態の監視

以下のストアドプロシージャを使用して、キューの状態を確認およびリセットできます。

現在の状態の確認

CALL dbms_ccl.show_ccl_queue();

出力例:

+------+-------+-------------------+---------+---------+----------+
| ID   | TYPE  | CONCURRENCY_COUNT | MATCHED | RUNNING | WAITTING |
+------+-------+-------------------+---------+---------+----------+
|    1 | QUEUE |                64 |       1 |       0 |        0 |
|    2 | QUEUE |                64 |   40744 |      65 |        6 |
|    3 | QUEUE |                64 |       0 |       0 |        0 |
|    4 | QUEUE |                64 |       0 |       0 |        0 |
+------+-------+-------------------+---------+---------+----------+

出力フィールドの説明:

フィールド説明
CONCURRENCY_COUNTこのバケットで許可される最大同時実行ステートメント数
MATCHEDこのバケットのルールに一致したステートメントの総数
RUNNINGこのバケットで現在実行中のステートメント
WAITTING現在キューで待機中のステートメント

キューのデータのリセット

dbms_ccl.flush_ccl_queue() は、メモリ上のキュー統計情報をクリアし、現在の状態を返します。

CALL dbms_ccl.flush_ccl_queue();
CALL dbms_ccl.show_ccl_queue();

フラッシュ後の出力例:

+------+-------+-------------------+---------+---------+----------+
| ID   | TYPE  | CONCURRENCY_COUNT | MATCHED | RUNNING | WAITTING |
+------+-------+-------------------+---------+---------+----------+
|    1 | QUEUE |                64 |       0 |       0 |        0 |
|    2 | QUEUE |                64 |       0 |       0 |        0 |
|    3 | QUEUE |                64 |       0 |       0 |        0 |
|    4 | QUEUE |                64 |       0 |       0 |        0 |
+------+-------+-------------------+---------+---------+----------+

アプリケーションコードの変更なしでキューのヒントを適用する

PolarDB for MySQL 5.7 および 8.0 では、ステートメントキューとステートメントアウトラインを組み合わせることで、サーバー側から既存の SQL ステートメントにキューのヒントを注入できます。アプリケーションコードの変更は不要です。

PolarDB for MySQL 5.6 では構文が異なるため、この統合機能は利用できません。

以下の例では、Sysbench の update_non_index.lua スクリプトを用いて、このワークフローを実証します。

テストスキーマ:

CREATE TABLE `sbtest1` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `k` int(10) unsigned NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 MAX_ROWS=1000000;

対象ステートメント:

UPDATE sbtest1 SET c='xpchild' WHERE id=0;

手順:

  1. オンラインでキューのヒントを注入するステートメントアウトラインを作成します。

    CALL DBMS_OUTLN.add_optimizer_outline('test', '', 1,
        ' /*+ ccl_queue_field("id") */ ',
        "UPDATE sbtest1 SET c='xpchild' WHERE id=0");
  2. アウトラインが正常に作成されたことを確認します。

    CALL dbms_outln.show_outline();

    期待される出力:

    +------+--------+------------------------------------------------------------------+-----------+-------+------+--------------------------------+------+----------+---------------------------------------------+
    | ID   | SCHEMA | DIGEST                                                           | TYPE      | SCOPE | POS  | HINT                           | HIT  | OVERFLOW | DIGEST_TEXT                                 |
    +------+--------+------------------------------------------------------------------+-----------+-------+------+--------------------------------+------+----------+---------------------------------------------+
    |    1 | test   | 7b945614749e541e0600753367884acff5df7e7ee2f5fb0af5ea58897910f023 | OPTIMIZER |       |    1 |  /*+ ccl_queue_field("id") */  |    0 |        0 | UPDATE `sbtest1` SET `c` = ? WHERE `id` = ? |
    +------+--------+------------------------------------------------------------------+-----------+-------+------+--------------------------------+------+----------+---------------------------------------------+
  3. EXPLAIN を実行して、ヒントが有効になっていることを確認します。

    EXPLAIN UPDATE sbtest1 SET c='xpchild' WHERE id=0;
    SHOW WARNINGS;

    SHOW WARNINGS の出力には、注入されたヒントが表示されるはずです。

    +-------+------+-----------------------------------------------------------------------------------------------------------------------------+
    | Level | Code | Message                                                                                                                     |
    +-------+------+-----------------------------------------------------------------------------------------------------------------------------+
    | Note  | 1003 | update /*+ CCL_QUEUE_FIELD('id') */ `test`.`sbtest1` set `test`.`sbtest1`.`c` = 'xpchild' where (`test`.`sbtest1`.`id` = 0) |
    +-------+------+-----------------------------------------------------------------------------------------------------------------------------+
  4. テスト開始前に、キューに活動がないことを確認します。

    CALL dbms_ccl.show_ccl_queue();
  5. Sysbench テストを実行します。

    sysbench \
      --mysql-host={$ip} \
      --mysql-port={$port} \
      --mysql-db=test \
      --test=./sysbench/share/sysbench/update_non_index.lua \
      --oltp-tables-count=1 \
      --oltp_table_size=1 \
      --num-threads=128 \
      --mysql-user=u0
  6. テスト中にキューの状態を確認し、ステートメントが正しくルーティングされていることを検証します。

    CALL dbms_ccl.show_ccl_queue();

    テスト中の期待される出力:

    +------+-------+-------------------+---------+---------+----------+
    | ID   | TYPE  | CONCURRENCY_COUNT | MATCHED | RUNNING | WAITTING |
    +------+-------+-------------------+---------+---------+----------+
    |    1 | QUEUE |                64 |   10996 |      63 |        4 |
    |    2 | QUEUE |                64 |       0 |       0 |        0 |
    |    3 | QUEUE |                64 |       0 |       0 |        0 |
    |    4 | QUEUE |                64 |       0 |       0 |        0 |
    +------+-------+-------------------+---------+---------+----------+

    アウトラインのヒット数とも照合します。

    CALL dbms_outln.show_outline();

    本テスト実行では、115,795 件のステートメントがアウトラインルールに一致し、そのうち 10,996 件がキューに到達、63 件が同時実行中、4 件が待機中でした。

次のステップ