📣

TiDB Cloud Serverless が
Starter
に変わりました!このページは自動翻訳されたものです。
原文はこちらからご覧ください。

AUTO_RANDOM v3.1.0 の新機能

ユーザーシナリオ

AUTO_RANDOMの値はランダムかつ一意であるため、TiDBが連続したIDを割り当てることで単一storageノードに書き込みホットスポットが発生するのを回避するため、 AUTO_INCREMENTの代わりにAUTO_RANDOM使用されることがよくあります。現在のAUTO_INCREMENT列が主キーで、型がBIGINT場合、 ALTER TABLE t MODIFY COLUMN id BIGINT AUTO_RANDOM(5);ステートメントを実行してAUTO_INCREMENTからAUTO_RANDOMに切り替えることができます。

テーブルの作成文のAUTO_RANDOM_BASEパラメータは、初期増分値auto_randomを設定するために使用されます。このオプションは内部インターフェースの一部とみなすことができます。このパラメータは無視できます。

基本概念

AUTO_RANDOMは、 BIGINT列に値を自動的に割り当てるために使用される列属性です。自動的に割り当てられる値はランダムかつ一意です。

AUTO_RANDOM列目のテーブルを作成するには、以下のステートメントを使用します。3列目AUTO_RANDOM主キーに含まれている必要があり、 AUTO_RANDOM列目は主キーの最初の列です。

CREATE TABLE t (a BIGINT AUTO_RANDOM, b VARCHAR(255), PRIMARY KEY (a)); CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b VARCHAR(255)); CREATE TABLE t (a BIGINT AUTO_RANDOM(6), b VARCHAR(255), PRIMARY KEY (a)); CREATE TABLE t (a BIGINT AUTO_RANDOM(5, 54), b VARCHAR(255), PRIMARY KEY (a)); CREATE TABLE t (a BIGINT AUTO_RANDOM(5, 54), b VARCHAR(255), PRIMARY KEY (a, b));

キーワードAUTO_RANDOM実行コメントで囲むことができます。詳細についてはTiDB固有のコメント構文を参照してください。

CREATE TABLE t (a bigint /*T![auto_rand] AUTO_RANDOM */, b VARCHAR(255), PRIMARY KEY (a)); CREATE TABLE t (a bigint PRIMARY KEY /*T![auto_rand] AUTO_RANDOM */, b VARCHAR(255)); CREATE TABLE t (a BIGINT /*T![auto_rand] AUTO_RANDOM(6) */, b VARCHAR(255), PRIMARY KEY (a)); CREATE TABLE t (a BIGINT /*T![auto_rand] AUTO_RANDOM(5, 54) */, b VARCHAR(255), PRIMARY KEY (a));

INSERTステートメントを実行すると、次のようになります。

  • AUTO_RANDOM列目の値を明示的に指定すると、そのままテーブルに挿入されます。
  • AUTO_RANDOM列の値を明示的に指定しない場合は、TiDB によってランダムな値が生成され、テーブルに挿入されます。
tidb> CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b VARCHAR(255)) /*T! PRE_SPLIT_REGIONS=2 */ ; Query OK, 0 rows affected, 1 warning (0.01 sec) tidb> INSERT INTO t(a, b) VALUES (1, 'string'); Query OK, 1 row affected (0.00 sec) tidb> SELECT * FROM t; +---+--------+ | a | b | +---+--------+ | 1 | string | +---+--------+ 1 row in set (0.01 sec) tidb> INSERT INTO t(b) VALUES ('string2'); Query OK, 1 row affected (0.00 sec) tidb> INSERT INTO t(b) VALUES ('string3'); Query OK, 1 row affected (0.00 sec) tidb> SELECT * FROM t; +---------------------+---------+ | a | b | +---------------------+---------+ | 1 | string | | 1152921504606846978 | string2 | | 4899916394579099651 | string3 | +---------------------+---------+ 3 rows in set (0.00 sec) tidb> SHOW CREATE TABLE t; +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | t | CREATE TABLE `t` ( `a` bigint NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */, `b` varchar(255) DEFAULT NULL, PRIMARY KEY (`a`) /*T![clustered_index] CLUSTERED */ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T! PRE_SPLIT_REGIONS=2 */ | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) tidb> SHOW TABLE t REGIONS; +-----------+-----------------------------+-----------------------------+-----------+-----------------+---------------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ | REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS | SCHEDULING_CONSTRAINTS | SCHEDULING_STATE | +-----------+-----------------------------+-----------------------------+-----------+-----------------+---------------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ | 62798 | t_158_ | t_158_r_2305843009213693952 | 62810 | 28 | 62811, 62812, 62810 | 0 | 151 | 0 | 1 | 0 | | | | 62802 | t_158_r_2305843009213693952 | t_158_r_4611686018427387904 | 62803 | 1 | 62803, 62804, 62805 | 0 | 39 | 0 | 1 | 0 | | | | 62806 | t_158_r_4611686018427387904 | t_158_r_6917529027641081856 | 62813 | 4 | 62813, 62814, 62815 | 0 | 160 | 0 | 1 | 0 | | | | 9289 | t_158_r_6917529027641081856 | 78000000 | 48268 | 1 | 48268, 58951, 62791 | 0 | 10628 | 43639 | 2 | 7999 | | | +-----------+-----------------------------+-----------------------------+-----------+-----------------+---------------------+------------+---------------+------------+----------------------+------------------+------------------------+------------------+ 4 rows in set (0.00 sec)

TiDB によって自動的に割り当てられるAUTO_RANDOM(S, R)列の値の合計は 64 ビットです。

  • Sはシャードビット数です。値の範囲は1から15です。デフォルト値は5です。
  • Rは自動割り当て範囲の合計長です。値の範囲は32から64 。デフォルト値は64です。

符号付きビットを持つAUTO_RANDOM値の構造は次のとおりです。

符号付きビット予約ビット破片の断片自動インクリメントビット
1ビット64-RビットSビットR-1-Sビット

符号付きビットのないAUTO_RANDOM値の構造は次のとおりです。

予約ビット破片の断片自動インクリメントビット
64-RビットSビットR-Sビット
  • 値に符号付きビットがあるかどうかは、対応する列にUNSIGNED属性があるかどうかによって決まります。
  • 符号ビットの長さは、属性UNSIGNED有無によって決まります。属性UNSIGNEDがある場合、長さは0です。そうでない場合、長さは1です。
  • 予約ビットの長さは64-Rです。予約ビットは常に0です。
  • シャードビットの内容は、現在のトランザクションの開始時刻のハッシュ値を計算することで得られます。異なるシャードビット長(10など)を使用する場合は、テーブル作成時にAUTO_RANDOM(10)指定します。
  • 自動インクリメントビットの値はstorageエンジンに格納され、順次割り当てられます。新しい値が割り当てられるたびに、値は1ずつ増加します。自動インクリメントビットは、 AUTO_RANDOMの値がグローバルに一意であることを保証します。自動インクリメントビットが使い果たされると、値が再び割り当てられる際にエラーFailed to read auto-increment value from storage engineが報告されます。
  • 値の範囲:最終的に生成される値の最大ビット数 = シャードビット数 + 自動インクリメントビット数。符号付き列の範囲は[-(2^(R-1))+1, (2^(R-1))-1] 、符号なし列の範囲は[0, (2^R)-1]です。
  • AUTO_RANDOM PRE_SPLIT_REGIONSと組み合わせて使用できます。テーブルが正常に作成されると、 PRE_SPLIT_REGIONSテーブル内のデータを2^(PRE_SPLIT_REGIONS)で指定された数のリージョンに事前に分割します。

注記:

シャードビットの選択( S ):

  • 利用可能なビット数は合計64ビットであるため、シャードビット長は自動インクリメントビット長に影響します。つまり、シャードビット長が増加すると自動インクリメントビット長は減少し、逆もまた同様です。したがって、割り当てられた値のランダム性と利用可能なスペースのバランスをとる必要があります。
  • ベストプラクティスは、シャードビットをlog(2, x)に設定することです。ここで、 x現在のstorageエンジンの数です。例えば、TiDB クラスターに TiKV ノードが 16 個ある場合、シャードビットをlog(2, 16) (つまり4に設定できます。すべてのリージョンが各 TiKV ノードに均等にスケジュールされると、一括書き込みの負荷が複数の TiKV ノードに均等に分散され、リソース使用率を最大化できます。

範囲の選択( R ):

  • 通常、アプリケーションの数値型が完全な 64 ビット整数を表現できない場合は、 Rパラメータを設定する必要があります。
  • 例えば、JSONの数値の範囲は[-(2^53)+1, (2^53)-1]です。TiDBは、 AUTO_RANDOM(5)と定義された列にこの範囲を超える整数を簡単に割り当ててしまう可能性があり、アプリケーションがその列を読み取った際に予期しない動作を引き起こす可能性があります。このような場合、符号付き列の場合はAUTO_RANDOM(5) AUTO_RANDOM(5, 54)に、符号なし列の場合はAUTO_RANDOM(5) AUTO_RANDOM(5, 53)に置き換えることで、TiDBが列に9007199254740991 (2^53-1) を超える整数を割り当てないようにすることができます。

AUTO_RANDOM列に暗黙的に割り当てられた値はlast_insert_id()影響します。TiDB が最後に暗黙的に割り当てた ID を取得するには、 SELECT last_insert_id ()ステートメントを使用できます。

列番号がAUTO_RANDOMであるテーブルのシャードビット数を確認するには、 SHOW CREATE TABLEステートメントを実行します。また、 information_schema.tablesシステムテーブルの列番号TIDB_ROW_ID_SHARDING_INFOで、 PK_AUTO_RANDOM_BITS=xのモードの値を確認することもできますxはシャードビット数です。

AUTO_RANDOM列のテーブルを作成した後、 SHOW WARNINGS使用して最大暗黙的割り当て時間を表示できます。

CREATE TABLE t (a BIGINT AUTO_RANDOM, b VARCHAR(255), PRIMARY KEY (a)); SHOW WARNINGS;

出力は次のようになります。

+-------+------+---------------------------------------------------------+ | Level | Code | Message | +-------+------+---------------------------------------------------------+ | Note | 1105 | Available implicit allocation times: 288230376151711743 | +-------+------+---------------------------------------------------------+ 1 row in set (0.00 sec)

IDの暗黙的な割り当てルール

TiDBは、 AUTO_INCREMENT列と同様に、 AUTO_RANDOM列にも暗黙的に値を割り当てます。これらの値は、セッションレベルのシステム変数auto_increment_incrementauto_increment_offsetによって制御されます。暗黙的に割り当てられた値の自動インクリメントビット(ID)は、式(ID - auto_increment_offset) % auto_increment_increment == 0に従います。

自動増分IDキャッシュをクリアする

複数のTiDBサーバーインスタンスが存在する環境で、 AUTO_RANDOM列目に明示的な値を持つデータを挿入すると、 AUTO_INCREMENT列目と同様に、IDの衝突が発生する可能性があります。明示的な挿入で使用されたID値が、TiDBが自動生成に使用する内部カウンターと競合すると、エラーが発生する可能性があります。

衝突が発生する仕組みは以下のとおりです。 AUTO_RANDOM IDはランダムビットと自動増分部分で構成されています。TiDBはこの自動増分部分に内部カウンタを使用します。自動増分部分がカウンタの次の値と一致するIDを明示的に挿入すると、TiDBが後で同じIDを自動生成しようとする際に、重複キーエラーが発生する可能性があります。詳細については、 AUTO_INCREMENT 一意性参照してください。

TiDBインスタンスが1つの場合、ノードは明示的な挿入を処理する際に内部カウンターを自動的に調整し、将来の衝突を防ぐため、この問題は発生しません。一方、複数のTiDBノードがある場合、各ノードは独自のIDキャッシュを保持しており、明示的な挿入後に衝突を防ぐには、このキャッシュをクリアする必要があります。これらの未割り当てのキャッシュIDをクリアして衝突の可能性を回避するには、次の2つの方法があります。

ALTER TABLE t AUTO_RANDOM_BASE=0;

このステートメントは適切な基数を自動的に決定します。1 Can't reset AUTO_INCREMENT to 0 without FORCE option, using XXX insteadような警告メッセージが表示されますが、基数は変更されるため、この警告は無視しても問題ありません。

注記:

FORCEキーワードを使用してAUTO_RANDOM_BASEから0設定することはできません。これを試みるとエラーが発生します。

オプション2: 特定の基本値を手動で設定する

特定の基本値 (たとえば、 1000 ) を設定する必要がある場合は、 FORCEキーワードを使用します。

ALTER TABLE t FORCE AUTO_RANDOM_BASE = 1000;

このアプローチは、適切な基本値を自分で決定する必要があるため、あまり便利ではありません。

注記:

FORCE使用する場合は、ゼロ以外の正の整数を指定する必要があります。

どちらのコマンドも、すべてのTiDBノードにおける後続のAUTO_RANDOM値生成で使用される自動インクリメントビットの開始点を変更します。すでに割り当てられているIDには影響しません。

制限

AUTO_RANDOM使用する場合は、次の制限に注意してください。

  • 明示的に値を挿入するには、システム変数@@allow_auto_random_explicit_insertの値を1 (デフォルトは0 )に設定する必要があります。データを挿入する際に、属性AUTO_RANDOM持つ列に明示的に値を指定することは推奨されません。そうしないと、このテーブルに自動的に割り当てられる数値が事前に使い果たされてしまう可能性があります。
  • この属性は、主キー列にのみBIGINT型で指定してください。それ以外の場合はエラーが発生します。また、主キーの属性がNONCLUSTEREDの場合、整数型の主キーであってもAUTO_RANDOMサポートされませんCLUSTERED型の主キーの詳細については、 クラスター化インデックスを参照してください。
  • ALTER TABLE使用してAUTO_RANDOM属性を変更することはできません (この属性の追加や削除を含む)。
  • 最大値が列タイプの最大値に近い場合は、 ALTER TABLEを使用してAUTO_INCREMENTからAUTO_RANDOMに変更することはできません。
  • AUTO_RANDOM属性で指定された主キー列の列タイプを変更することはできません。
  • 同じ列に同時にAUTO_RANDOMAUTO_INCREMENT指定することはできません。
  • 同じ列にAUTO_RANDOMDEFAULT (列のデフォルト値) を同時に指定することはできません。
  • 列にAUTO_RANDOM使用されている場合、自動生成される値が非常に大きくなる可能性があるため、列属性をAUTO_INCREMENTに戻すのは困難です。

このページは役に立ちましたか?