AUTO_RANDOM v3.1.0の新機能
ユーザーシナリオ
AUTO_RANDOMの値はランダムで一意であるため、TiDB が連続した ID を割り当てることによって発生する単一ストレージ ノードでの書き込みホットスポットを回避するために、 AUTO_INCREMENTの代わりにAUTO_RANDOMがよく使用されます。現在のAUTO_INCREMENT列が主キーで、タイプがBIGINTの場合、 ALTER TABLE t MODIFY COLUMN id BIGINT AUTO_RANDOM(5);ステートメントを実行してAUTO_INCREMENTからAUTO_RANDOMに切り替えることができます。
TiDB で同時書き込み負荷の高いワークロードを処理する方法の詳細については、 高度な同時書き込みのベスト プラクティスを参照してください。
基本概念
AUTO_RANDOMは、 BIGINT列に値を自動的に割り当てるために使用される列属性です。自動的に割り当てられる値はランダムで一意です。
AUTO_RANDOM列のテーブルを作成するには、次のステートメントを使用できます。 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));
実行可能なコメントでキーワード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));
INSERTステートメントを実行すると、次のようになります。
AUTO_RANDOM列の値を明示的に指定すると、そのままテーブルに挿入されます。AUTO_RANDOM列の値を明示的に指定しない場合、TiDB はランダムな値を生成し、それをテーブルに挿入します。
tidb> CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b VARCHAR(255));
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 によって自動的に割り当てられるAUTO_RANDOM(S)列の値は、合計 64 ビットです。 Sはシャード ビットの数です。値の範囲は1 ~ 15です。デフォルト値は5です。
AUTO_RANDOM値の構造は次のとおりです。
| 総ビット数 | 符号ビット | シャードビット | 自動インクリメント ビット |
|---|---|---|---|
| 64ビット | 0/1 ビット | S ビット | (64-1-S) ビット |
- 符号ビットの長さは、
UNSIGNED属性の存在によって決まります。UNSIGNED属性がある場合、長さは0です。それ以外の場合、長さは1です。 - シャード ビットの内容は、現在のトランザクションの開始時刻のハッシュ値を計算することによって取得されます。別の長さのシャード ビット (10 など) を使用するには、テーブルの作成時に
AUTO_RANDOM(10)を指定します。 - 自動インクリメント ビットの値は、ストレージ エンジンに格納され、順番に割り当てられます。新しい値が割り当てられるたびに、値は 1 ずつインクリメントされます。自動インクリメント ビットは、
AUTO_RANDOMの値がグローバルに一意であることを保証します。自動インクリメント ビットが使い果たされると、値が再度割り当てられるときにエラーFailed to read auto-increment value from storage engineが報告されます。
ノート:
シャード ビットの選択 (
S):
- 合計 64 の使用可能なビットがあるため、シャード ビット長は自動インクリメント ビット長に影響します。つまり、シャード ビットの長さが増加すると、自動インクリメント ビットの長さが減少し、逆もまた同様です。したがって、割り当てられた値のランダム性と使用可能なスペースのバランスを取る必要があります。
- ベスト プラクティスは、シャード ビットを
log(2, x)に設定することです。ここで、xはストレージ エンジンの現在の数です。たとえば、TiDB クラスターに 16 個の TiKV ノードがある場合、シャード ビットをlog(2, 16)、つまり4に設定できます。すべてのリージョンが各 TiKV ノードに均等にスケジュールされた後、バルク書き込みの負荷を異なる TiKV ノードに均等に分散して、リソースの使用率を最大化できます。
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を使用する場合は、次の制限に注意してください。
- 値を明示的に挿入するには、システム変数
@@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_RANDOMとAUTO_INCREMENTを同時に指定することはできません。 - 同じ列に
AUTO_RANDOMとDEFAULT(列のデフォルト値) を同時に指定することはできません。 - 列で
AUTO_RANDOMを使用すると、自動生成された値が非常に大きくなる可能性があるため、列属性をAUTO_INCREMENTに戻すのは困難です。