# AUTO_RANDOMをTiDBで使用する

### 概要
+ これらの演習では、`AUTO_RANDOM`属性に関する実践的な経験を得ることができます。`AUTO_RANDOM`属性を持つテーブルをプライマリキーで作成し、そのテーブルからクエリを実行します。
+ `AUTO_RANDOM`は、連続したIDの割り当てによって引き起こされる書き込みのホットスポットを防ぐために、しばしば`AUTO_INCREMENT`の代わりに使用されます。
+ `AUTO_RANDOM(3)`属性を持つテーブルを作成し、3つのシャードビットを示します。すべてのリージョンが均等に各TiKVノードにスケジュールされた後、bulk writeの負荷は可能な限り異なるTiKVノードに均等に分配され、リソース利用率を最大化できます。

 <img src="./diagram/2013E051_ja_001_20230407.png" width="50%" align="top"/>

### 注意
+ いくつかのステップでは、2つの異なるターミナルウィンドウでコマンドを入力する必要があります。2つのターミナルを起動し、演習の間ずっと開いておくと便利でしょう。
+ この演習で利用する、`IP`、`port`、`username`、`password`、`directory`などは、あなたの環境と異なる場合があります。
+ ターミナルウィンドウの"`$`"とはOSプロンプトです。
+ ターミナルウィンドウ内の "`tidb>`" または "`mysql>`" は、SQL コマンドプロンプトです。
+ これらの演習は、ノートパソコンなどの単一のマシン上で実行することができます。

### 前提条件
+ macOSまたはLinuxを使用していること。
+ [lab repository](https://github.com/pingcap/tidb-course-201-lab.git)をクローン済みであること。
+ 演習「テスト用にTiDBクラスタを作成する」を完了していること。

### 所要時間
+ この演習は約15分程度かかります。

### タスク
1. `AUTO_RANDOM`属性を含むテーブルを作成します。
2. `AUTO_RANDOM`設定で生成されたIDが意図通りに適切にパーティションされていることを確認します。

### 手順
1. TiDBサーバーに接続します。

     + (a) `connect-cloud.sh`を使用して、TiDB Cloud Serverlessに接続します
       ```
       $ cd tidb-course-201-lab/scripts
       $ ./connect-cloud.sh
       ...
       tidb-cloud>
       ```

     + (b) `connect-4000.sh`を使用してTiDB Playgroundクラスタに接続します
       ```
       $ cd tidb-course-201-lab/scripts
       $ ./connect-4000.sh
       ...
       tidb:4000>
       ```

2. `test.auto_random_t1`テーブルを作成し、それにプライマリキー生成に割り当てられた8つのシャード（2 <sup>3</sup>）を持たせます。
     ```sql
     DROP TABLE IF EXISTS test.auto_random_t1;
     CREATE TABLE test.auto_random_t1 (
         id BIGINT PRIMARY KEY AUTO_RANDOM(3),
         name CHAR(255));
     ```

3. 別のターミナルウィンドウを開いて、`scripts`ディレクトリの下にある以下のスクリプトを確認します：`05-insert-loop.sh`および`misc/insert-into-auto-random.sql`。
     ```
     $ cat ./05-insert-loop.sh
     #!/bin/bash

     for i in {1..800};
       do
         mysql -h 127.0.0.1 -P 4000 -u root < ./misc/insert-into-auto-random.sql
       done;
     ```
     ```
     $ cat ./misc/insert-into-auto-random.sql
     INSERT INTO test.auto_random_t1
     VALUES (NULL, 'A');
     ```

4. `test.auto_random_t1`テーブルに800行を挿入するには、`scripts`ディレクトリ内の`05-insert-loop.sh`スクリプトを実行します。ただし、現在の`05-insert-loop.sh`の方法は効率が悪い場合があることに注意してください。バッチ挿入についての詳細については、「JavaでTiDBを活用する」コースを参照してください。
     ```
     $ ./05-insert-loop.sh
     ```

5. MySQLクライアントターミナルウィンドウに戻り、`test.auto_random_t1`テーブルの`PK_AUTO_RANDOM_BITS`属性を確認します。その値は３であるはずです。これは、ランダムな数値の生成プロセス中に8つのシャード（（2<sup>3</sup>）が利用されることを示します。
     ```sql
     SELECT TIDB_ROW_ID_SHARDING_INFO, TIDB_PK_TYPE
     FROM information_schema.tables
     WHERE table_schema='test'
     AND table_name='auto_random_t1';

     SELECT COUNT(*) FROM test.auto_random_t1;
     ```
     ```
     --------------
     SELECT TIDB_ROW_ID_SHARDING_INFO, TIDB_PK_TYPE
     FROM information_schema.tables
     WHERE table_schema='test'
     AND table_name='auto_random_t1'
     --------------

     +---------------------------+--------------+
     | TIDB_ROW_ID_SHARDING_INFO | TIDB_PK_TYPE |
     +---------------------------+--------------+
     | PK_AUTO_RANDOM_BITS=3     | CLUSTERED    |
     +---------------------------+--------------+
     1 row in set (0.00 sec)

     ...
     --------------
     SELECT COUNT(*) FROM test.auto_random_t1
     --------------

     +----------+
     | COUNT(*) |
     +----------+
     |      800 |
     +----------+
     1 row in set (0.00 sec)
     ```

6. 簡単なクエリを実行して、一般的なシャーディングの結果を確認します。クエリ結果の行数は8と等しくなるはずです。クエリは、右シフト（63引くシャードカウントビット）演算を使用して調べる必要のあるシャードのビットのみを抽出します。出力には、8つのシャードが使用されていることが示されます。
     ```sql
     SELECT id >> (63-3) as shard,
         COUNT(1) as rows_by_shard
     FROM test.auto_random_t1
     GROUP BY shard;
     ```
     ```
     --------------
     SELECT id >> (63-3) as shard,
         COUNT(1) as rows_by_shard
     FROM test.auto_random_t1
     GROUP BY shard
     --------------

     +-------+---------------+
     | shard | rows_by_shard |
     +-------+---------------+
     |     5 |            99 |
     |     0 |           102 |
     |     4 |            89 |
     |     1 |           118 |
     |     3 |            97 |
     |     6 |            82 |
     |     7 |           112 |
     |     2 |           101 |
     +-------+---------------+
     8 rows in set (0.00 sec)
     ```

7. `AUTO_RANDOM`シャードビットについてもっと学びたい場合は、[TiDBドキュメント](https://docs.pingcap.com/ja/tidb/stable/auto-random#basic-concepts)を参照してください。

## まとめ
TiDBの`AUTO_RANDOM`属性は、一意のIDを自動生成し、すべてのシャードの間で均等に配布することができるため、書き込みホットスポットの問題を緩和することができます。本番レベルのテストまたはデモが必要な場合は、[こちらをクリックして](https://pingcap.co.jp/contact-us/?utm_source=edu&utm_medium=referral&utm_campaign=201.3.E5)申し込んでください。

## 演習終わり