🐈

TiDBのSEQUENCEの性能

に公開

この記事について

前回、TiDBでIDを1つずつインクリメントさせたい - AUTO_INCREMENTとSEQUENCEという記事でTiDBのSEQUENCEオブジェクトを紹介しました。前回の記事ではSEQUENCEオブジェクトの基本的な操作や使い方を説明し、MySQLのAUTO_INCREMENTと同等の動作を実現するための設定などについても触れました。

本記事では実際にSEQUENCEオブジェクトを1つずつ採番するための仕組みとして利用する場合の性能を検証した結果を皆様にご報告いたします。具体的には以下2つの観点で検証を行い、 それぞれのケースにおいて、TiDBのAUTO_INCREMENT(AUTO_ID_CACHE 1)の結果と比較しました。

  1. レイテンシーの検証: 所定の件数のレコードを挿入するのにかかった時間を計測する
  2. スループットの確認: 一定時間内に挿入されたレコード数を計測する

対象となるSEQUENCEオブジェクトとAUTO_INCREMENTの設定は以下のとおりです。

  1. SEQUENCEオブジェクトにNO CACHEを付与する
  2. AUTO_INCREMENTにAUTO_ID_CACHE 1を設定する

想定読者は前回の記事を読んでいることとしますので、TiDBのAUTO_INCREMENTに関する説明は本記事では割愛しております。

検証環境

本検証はTiDB CloudのDedicatedクラスターを用いました。リージョンやバージョン情報などは以下のとおりです。

  • Provider: AWS
  • Region: Tokyo (ap-northeast-1)
  • Cluster Size
    • TiDB: 8 vCPU, 16 GiB
    • TiKV: 8 vCPU, 32 GiB, 200 GiB Storage * 3
  • Version: v8.1.2

検証方法について

本検証では以下のテーブル定義を行い、このテーブルに対してID列だけを追加するINSERT文を実行することとし、IDの自動採番以外の処理が極力発生しないようにしました。

-- テーブル定義
CREATE TABLE t1 (id BIGINT PRIMARY KEY AUTO_INCREMENT) AUTO_ID_CACHE 1;
    
CREATE SEQUENCE IF NOT EXISTS seq_t2 NO CACHE;
CREATE TABLE t2 (id BIGINT PRIMARY KEY DEFAULT NEXT VALUE FOR seq_t2);

-- INSERT文
INSERT INTO t1 VALUES ();
INSERT INTO t2 VALUES ();

上記のINSERT文をtiup bench rawsqlコマンドを用いて所定の回数および一定時間だけクエリを繰り返し実行して性能を計測しました。ただし、後述しますが、レイテンシーの検証においてはこの方法は適切ではなかったため、レイテンシーの結果および評価については参考としてください。

レイテンシーの検証

SEQUENCEオブジェクトとAUTO_INCREMENTの場合で、レイテンシーを比較検証するために、所定のレコード数(1,000、5,000、10,000の3パターン)を挿入するのにかかった時間をそれぞれ10回計測しました。また、スケーラビリティも確認するためにTiDBノードを1台から3台までの3パターンで実施しました。先に結果の考察を記載します。

結果の考察

  • 各テストケースの比率から、SEQUENCEのレイテンシーは概ねAUTO_INCREMENTの2倍程度であると言える。
  • 挿入するレコード数が増えるにつれて、AUTO_INCREMENTのほうがSEQUENCEよりも増分が少なく、AUTO_INCREMENTのほうが性能が劣化しにくいと言える。
    • AUTO_INCREMENTの場合はIDを一定の範囲でキャッシュしているためである。
  • insert処理のレイテンシーに関して、スケーラビリティがあるとは言えない。
    • 今回のinsert処理では自動採番が行われるのみだが、自動採番処理においてTiDBないしはTiKVの台数は関係ないため。
    • 例えば、IDの取得にキャッシュが効いていればAUTO_INCREMENTのリーダーとなっているTiDBノードからIDを取得するだけだし、今回のSEQUENCEのようにキャッシュが効いていない(NO CACHE)場合でも結局は1台のTiKVからIDを取得するだけなので。

計測データ

以下に計測したレイテンシーのデータを記載しますが、注意があります。今回の検証で、レイテンシーはtiup bench rawsqlの処理にかかった時間を計測しました。しかし、これではtiup bench rawsqlが起動および終了するのにかかった時間も計測時間に含まれるため、実際のクエリのレイテンシーに多少のオーバーヘッドが含まれています。参考情報として計測時間を記載していますが、ここではAUTO_INCREMENTとSEQUENCEの比率に着目していただければと思います。

  • 単位:ミリ秒
  • 差分: SEQUENCE 平均 − AUTO_INCREMENT 平均
  • 比率: SEQUENCE 平均 ÷ AUTO_INCREMENT 平均

1 TiDB

レコード数 AUTO_INCREMENT
平均
SEQUENCE
平均
差分 (SEQ-AI) 比率 (SEQ/AI)
1,000 11,269.70 20,371.60 9,101.9 180.76 %
5,000 49,103.00 100,265.80 51,162.8 204.19 %
10,000 111,436.50 196,256.40 84,819.9 176.12 %

2 TiDB

レコード数 AUTO_INCREMENT
平均
SEQUENCE
平均
差分 (SEQ-AI) 比率 (SEQ/AI)
1,000 9,232.80 21,114.00 11,881.2 228.68 %
5,000 45,820.40 103,506.80 57,686.4 225.90 %
10,000 102,044.20 205,618.70 103,574.5 201.50 %

3 TiDB

レコード数 AUTO_INCREMENT平均 SEQUENCE平均 差分 (SEQ-AI) 比率 (SEQ/AI)
1,000 8,969.80 21,054.90 12,085.1 234.73 %
5,000 50,634.60 99,175.00 48,540.4 195.86 %
10,000 102,862.50 197,794.10 94,931.6 192.29 %

スループットの検証

こちらも先に結果の考察から記載します。

結果の考察

  • AUTO_INCREMENTはスレッド数に応じてほぼ線形に性能が向上するのに対し、SEQUENCEのスループット性能はスレッド数が8で頭打ちになる
  • SEQUENCEのスループット性能はTiDBノードを増やしても向上しない
  • AUTO_INCREMENTと比べて、SEQUENCEはスレッド数が増えるにつれて差がつきやすく、並列度が高くなるほどAUTO_INCREMENTが優位である

計測データ

スループットの検証もレイテンシーの場合と同様にtiup bench rawsqlコマンドを利用していますが、ベンチマークスクリプトのオーバーヘッドは結果に影響しません。

1 TiDB

thread AUTO_INCREMENT 平均 SEQUENCE 平均 差分 (SEQ-AI) 比率 (SEQ/AI)
1 50 939.30 33 032.60 –17 906.7 64.85 %
8 431 172.60 54 782.40 –376 390.2 12.71 %
16 895 646.30 54 700.90 –840 945.4 6.11 %
24 1 220 428.00 54 596.10 –1 165 831.9 4.47 %

2 TiDB

thread AUTO_INCREMENT 平均 SEQUENCE 平均 差分 (SEQ-AI) 比率 (SEQ/AI)
1 68 030.70 29 029.50 –39 001.2 42.67 %
8 456 034.80 52 294.20 –403 740.6 11.47 %
16 868 438.70 53 706.70 –814 732.0 6.18 %
24 1 280 983.40 51 588.50 –1 229 394.9 4.03 %

3 TiDB

thread AUTO_INCREMENT 平均 SEQUENCE 平均 差分 (SEQ-AI) 比率 (SEQ/AI)
1 65 567.90 29 093.60 –36 474.3 44.37 %
8 488 959.80 48 922.50 –440 031.3 10.01 %
16 960 010.90 49 655.10 –910 355.8 5.17 %
24 1 337 679.60 49 931.90 –1 287 747.7 3.73 %

検証まとめ

  • 本検証ではMySQLのAUTO_INCREMENTに近い動作をするように、TiDBのAUTO_INCREMENTではAUTO_ID_CACHE 1を、SEQUENCEオブジェクトにはNO CACHEを設定して、レイテンシーとスループットの両面から性能を評価しました
  • SEQUENCEオブジェクトの性能をの両方で評価し、AUTO_INCREMENTの場合と比較しました
  • SEQUENCEオブジェクトのレイテンシーはAUTO_INCREMENTの約2倍程度で、AUTO_INCREMENTのほうが高速でした
  • SEQUENCEオブジェクトのスループット性能は並列度が8で頭打ちになるのに対し、AUTO_INCREMENTは並列度に応じて性能が上がります

これらの結果を踏まえて、SEQUENCEオブジェクトが適したユースケースは例えば以下のようになるでしょう。

  • 更新頻度が数十QPS程度のテーブル
  • 大量にデータの追加や更新が行われるが、夜間バッチなどで処理されるので多少の遅延が許容されるようなテーブル

一方で、データの追加や更新が常時行われていて処理の遅延が許容できない、あるいは多くのクライアントから一斉にデータの追加や更新が行われるような状況ではSEQUENCEオブジェクトを使うべきではないかもしれません。

GitHubで編集を提案

Discussion