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
に戻すのは困難です。