# パーティションテーブル

### 概要
+ これらの演習を通して、パーティションテーブルを使ってクエリのパフォーマンスを向上させる方法を学びます。
+ パーティションテーブルは、ハッシュパーティション、レンジパーティション、リストパーティションの3種類に分類できます。

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

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

## 演習 1: ハッシュパーティションテーブル

### 概要
+ この演習を通じて、ハッシュパーティションテーブルの特性を学びます。これにより、データが指定された数のパーティションに均等に分散されます。
+ まず、同じモックデータが入力された非パーティションテーブルとハッシュパーティションテーブルを作成します。次に、特定のクエリの実行計画を分析します。

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

### タスク
1. TiDBサーバーに接続します。
2. ハッシュパーティションのテーブルを作成します。
3. 実行計画を確認し、さまざまなクエリ述語でのハッシュパーティションテーブルの動作を観察します。


### 手順
1. TiDBサーバーに接続します。TiDB Playground クラスタが起動していない場合は、`tidb-course-201-lab/scripts/`フォルダーにあるスクリプト`playground-start.sh`を実行して、Playground クラスタを起動します。
   ```
   $ cd tidb-course-201-lab/scripts
   $ ./connect-4000.sh
   ...
   tidb:4000>
   ```

2. 比較のために、`test.t0`という名前のパーティションされていないテーブルを作成します。
   ```sql
   DROP TABLE IF EXISTS test.t0;
   CREATE TABLE test.t0 (rid INT NOT NULL, gid INT NOT NULL);
   ```
   ```
   tidb:4000> DROP TABLE IF EXISTS test.t0;
   --------------
   DROP TABLE IF EXISTS test.t0
   --------------

   CREATE TABLE test.t0 (rid INT NOT NULL, gid INT NOT NULL);
   Query OK, 0 rows affected (2.06 sec)

   tidb:4000> CREATE TABLE test.t0 (rid INT NOT NULL, gid INT NOT NULL);
   --------------
   CREATE TABLE test.t0 (rid INT NOT NULL, gid INT NOT NULL)
   --------------

   Query OK, 0 rows affected (1.17 sec)
   ```

3. 主キーなしで16パーティションのハッシュパーティショニングを使用して、`test.t1`という名前のテーブルを作成します。`rid`という名前のカラムがハッシュキーになります。
   
   ```sql
   DROP TABLE IF EXISTS test.t1;
   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL)
       PARTITION BY HASH(rid)
       PARTITIONS 16;
   ```
   ```
   tidb:4000> DROP TABLE IF EXISTS test.t1;
   --------------
   DROP TABLE IF EXISTS test.t1
   --------------

   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL)
       PARTITION BY HASH(rid)
       PARTITIONS 16;
   Query OK, 0 rows affected (2.06 sec)

   tidb:4000> CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL)
       ->     PARTITION BY HASH(rid)
       ->     PARTITIONS 16;
   --------------
   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL)
       PARTITION BY HASH(rid)
       PARTITIONS 16
   --------------

   Query OK, 0 rows affected (1.09 sec)
   ```

4. `test.t0`と`test.t1` テーブルにそれぞれ524288行を入力します。`rid`カラムにはランダムな整数が入力されます。

   ```sql
   SOURCE 07-demo-populate-t0.sql
   SOURCE 07-demo-populate-t1.sql
   ```
   ```
   ...
   --------------
   ANALYZE TABLE test.t0
   --------------

   Query OK, 0 rows affected, 1 warning (1.60 sec)
   ...
   --------------
   ANALYZE TABLE test.t1
   --------------

   Query OK, 0 rows affected, 32 warnings (4.30 sec)
   ```

5. `test.t1`では、与えられた実行計画から、クエリを実行するには、`test.t1` 1つのパーティションだけをスキャンするだけで十分であることがわかります。

   `EXPLAIN ANALYZE` 出力にある`TableFullScan - id`の`actRows`カラムと`TableReader - id`の`access object`カラムに注目します。これは、データの16分の1しかスキャンされなかったことを示しており、`FULL TABLE SCAN`ではなく、`PARTITION SCAN`であることを示しています。
      ```sql
      PAGER LESS -S
      EXPLAIN ANALYZE SELECT * FROM test.t1 WHERE rid=7777777;
      ```
      ```
      +-------------------------+------------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------->
      | id                      | estRows    | actRows | task      | access object | execution info                                                                                                       >
      +-------------------------+------------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------->
      | TableReader_7           | 2.01       | 0       | root      | partition:p1  | time:28.7ms, loops:1, cop_task: {num: 1, max: 28.6ms, proc_keys: 32722, tot_proc: 28ms, rpc_num: 1, rpc_time: 28.6ms,>
      | └─Selection_6           | 2.01       | 0       | cop[tikv] |               | tikv_task:{time:28ms, loops:36}, scan_detail: {total_process_keys: 32722, total_process_keys_size: 1439752, total_key>
      |   └─TableFullScan_5     | 1048576.00 | 32722   | cop[tikv] | table:t1      | tikv_task:{time:27ms, loops:36}                                                                                      >
      +-------------------------+------------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------->
      ```

      `Q`を押して`PAGER`ビューを終了します。

6. `test.t0`では、与えられた実行計画は、クエリを実行するためには、`test.t0` テーブル全体をスキャンする必要があることを示しています。
   `EXPLAIN ANALYZE` 出力にある`TableFullScan - id`の`actRows`カラムと`TableReader - id`の`access object`カラムに注目します。これは、テーブルのデータ全体がスキャンされたことを示しており（テーブルは524288行あることを思い出します）、`FULL TABLE SCAN`であることを示しています。
      ```sql
      EXPLAIN ANALYZE SELECT * FROM test.t0 WHERE rid=7777777;
      ```
      ```
      +-------------------------+-----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------->
      | id                      | estRows   | actRows | task      | access object | execution info                                                                                                        >
      +-------------------------+-----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------->
      | TableReader_7           | 1.02      | 0       | root      |               | time:302.7ms, loops:1, cop_task: {num: 1, max: 302.3ms, proc_keys: 524288, tot_proc: 301ms, rpc_num: 1, rpc_time: 302.>
      | └─Selection_6           | 1.02      | 0       | cop[tikv] |               | tikv_task:{time:302ms, loops:517}, scan_detail: {total_process_keys: 524288, total_process_keys_size: 23068292, total_>
      |   └─TableFullScan_5     | 524288.00 | 524288  | cop[tikv] | table:t0      | tikv_task:{time:293ms, loops:517}                                                                                     >
      +-------------------------+-----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------->
      ```

      `Q`を押して、`PAGER`ビューを終了します。

7. 行が `test.t1` のパーティションに均等に分散されていることを確認します。この例では、パーティション名に`p0`、`p6`、`p12`を使用しています。`0 `と`15`の間の任意のパーティション番号を選択できます。

   ```sql
   NOPAGER
   SELECT COUNT(*) FROM test.t1 PARTITION (p0);
   SELECT COUNT(*) FROM test.t1 PARTITION (p6);
   SELECT COUNT(*) FROM test.t1 PARTITION (p12);
   ```
   ```
   tidb:4000> NOPAGER
   PAGER set to stdout
   tidb:4000>    SELECT COUNT(*) FROM test.t1 PARTITION (p0);
   --------------
   SELECT COUNT(*) FROM test.t1 PARTITION (p0)
   --------------

   +----------+
   | COUNT(*) |
   +----------+
   |    32602 |
   +----------+
   1 row in set (0.02 sec)

   tidb:4000>    SELECT COUNT(*) FROM test.t1 PARTITION (p6);
   --------------
   SELECT COUNT(*) FROM test.t1 PARTITION (p6)
   --------------

   +----------+
   | COUNT(*) |
   +----------+
   |    32661 |
   +----------+
   1 row in set (0.04 sec)

   tidb:4000>    SELECT COUNT(*) FROM test.t1 PARTITION (p12);
   --------------
   SELECT COUNT(*) FROM test.t1 PARTITION (p12)
   --------------

   +----------+
   | COUNT(*) |
   +----------+
   |    32801 |
   +----------+
   1 row in set (0.03 sec)
   ```

8. パーティションとTiKVリージョンの対応を確認します。現在、`test.t1` テーブルには16のリージョンがあるはずです。一方、パーティション化されていない`test.t0`テーブルでは、現時点で1つのリージョンのみが存在するはずです。

   ```sql
   SHOW TABLE test.t1 REGIONS\G
   SHOW TABLE test.t0 REGIONS\G
   ```
   ```
   tidb:4000> SHOW TABLE test.t1 REGIONS\G
   --------------
   SHOW TABLE test.t1 REGIONS
   --------------

   *************************** 1. row ***************************
                REGION_ID: 1083
                START_KEY: t_314_
                  END_KEY: t_315_
                LEADER_ID: 1084
          LEADER_STORE_ID: 3
                    PEERS: 1084
               SCATTERING: 0
            WRITTEN_BYTES: 0
               READ_BYTES: 0
     APPROXIMATE_SIZE(MB): 1
         APPROXIMATE_KEYS: 0
   SCHEDULING_CONSTRAINTS: 
         SCHEDULING_STATE: 
   .
   .
   .
   *************************** 16. row ***************************
                REGION_ID: 22
                START_KEY: t_329_
                  END_KEY: t_281474976710651_
                LEADER_ID: 262
          LEADER_STORE_ID: 3
                    PEERS: 262
               SCATTERING: 0
            WRITTEN_BYTES: 6737142
               READ_BYTES: 6562299
     APPROXIMATE_SIZE(MB): 1
         APPROXIMATE_KEYS: 0
   SCHEDULING_CONSTRAINTS: 
         SCHEDULING_STATE: 
   16 rows in set (0.03 sec)

   tidb:4000> SHOW TABLE test.t0 REGIONS\G
   --------------
   SHOW TABLE test.t0 REGIONS
   --------------

   *************************** 1. row ***************************
                REGION_ID: 1081
                START_KEY: t_310_
                  END_KEY: t_314_
                LEADER_ID: 1082
          LEADER_STORE_ID: 3
                    PEERS: 1082
               SCATTERING: 0
            WRITTEN_BYTES: 0
               READ_BYTES: 33554052
     APPROXIMATE_SIZE(MB): 45
         APPROXIMATE_KEYS: 680109
   SCHEDULING_CONSTRAINTS: 
         SCHEDULING_STATE: 
   1 row in set (0.01 sec)
   ```

## 演習 2: レンジパーティションテーブル

### 概要
+ この演習を通じて、レンジパーティションテーブルの特性を学びます。これにより、データが範囲値ごとに指定された数のパーティションに分散されます。
+ まず、モックデータが入力されたレンジパーティションテーブルを作成します。次に、特定のクエリの結果を分析します。

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

### タスク
1. レンジパーティションテーブルを作成します。
2. レンジパーティションテーブルの動作を観察します。

### 手順
1. インデックスを付けずに、4つのパーティションで構成されたレンジパーティションテーブル`test.t1`を作成します。`gid`という名前のカラムがレンジキーになります。
   
   ```sql
   DROP TABLE IF EXISTS test.t1;
   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY RANGE (gid) (
       PARTITION p0 VALUES LESS THAN (4),
       PARTITION p1 VALUES LESS THAN (9),
       PARTITION p2 VALUES LESS THAN (14),
       PARTITION p3 VALUES LESS THAN (MAXVALUE));
   ```
   ```
   tidb:4000> DROP TABLE IF EXISTS test.t1;
   --------------
   DROP TABLE IF EXISTS test.t1
   --------------

   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY RANGE (gid) (
       PARTITION p0 VALUES LESS THAN (4),
       PARTITION p1 VALUES LESS THAN (9),
       PARTITION p2 VALUES LESS THAN (14),
       PARTITION p3 VALUES LESS THAN (MAXVALUE));
   Query OK, 0 rows affected (2.06 sec)

   tidb:4000> CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY RANGE (gid) (
       ->     PARTITION p0 VALUES LESS THAN (4),
       ->     PARTITION p1 VALUES LESS THAN (9),
       ->     PARTITION p2 VALUES LESS THAN (14),
       ->     PARTITION p3 VALUES LESS THAN (MAXVALUE));
   --------------
   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY RANGE (gid) (
       PARTITION p0 VALUES LESS THAN (4),
       PARTITION p1 VALUES LESS THAN (9),
       PARTITION p2 VALUES LESS THAN (14),
       PARTITION p3 VALUES LESS THAN (MAXVALUE))
   --------------

   Query OK, 0 rows affected (1.05 sec)
   ```

2. 524288行の`test.t1`テーブルにモックデータを入力し、`gid`に対する行数の分布が以下に表示されている出力と同じであることを確認します。

   ```sql
   SOURCE 07-demo-populate-t1.sql
   SELECT gid, COUNT(*) FROM test.t1 GROUP BY gid ORDER BY 1;
   ```
   ```
   ...
   +-----+----------+
   | gid | COUNT(*) |
   +-----+----------+
   |   0 |        1 |
   |   1 |       19 |
   |   2 |      171 |
   |   3 |      969 |
   |   4 |     3876 |
   |   5 |    11628 |
   |   6 |    27132 |
   |   7 |    50388 |
   |   8 |    75582 |
   |   9 |    92378 |
   |  10 |    92378 |
   |  11 |    75582 |
   |  12 |    50388 |
   |  13 |    27132 |
   |  14 |    11628 |
   |  15 |     3876 |
   |  16 |      969 |
   |  17 |      171 |
   |  18 |       19 |
   |  19 |        1 |
   +-----+----------+
   20 rows in set (0.21 sec)
   ```

3. ステップ1のパーティションスキーマの設計とステップ2の`gid` 分散結果を考慮して、以下のクエリの出力を分析します。`p2` パーティションが行数が最も多い理由を説明してもらえますか。

   ```sql
   SELECT 'P0_COUNT', COUNT(*) FROM test.t1 PARTITION (p0)
   UNION ALL
   SELECT 'P1_COUNT', COUNT(*) FROM test.t1 PARTITION (p1)
   UNION ALL
   SELECT 'P2_COUNT', COUNT(*) FROM test.t1 PARTITION (p2)
   UNION ALL
   SELECT 'P3_COUNT', COUNT(*) FROM test.t1 PARTITION (p3)
   ORDER BY 1;
   ```
   ```
   ...
   +----------+----------+
   | P0_COUNT | COUNT(*) |
   +----------+----------+
   | P0_COUNT |     1160 |
   | P1_COUNT |   168606 |
   | P2_COUNT |   337858 |
   | P3_COUNT |    16664 |
   +----------+----------+
   4 rows in set (0.16 sec)
   ```

4. 次の実行計画に従い、`TableFullScan - id`の`actRows`カラムと`TableReader - id`の`access object`カラムに注意します。対象の行は同じパーティション`p3`にあるため、スキャンされるのは1つのパーティションのみで、パーティション`p3`には15から最大までの値が含まれています。

   ```sql
   PAGER LESS -S
   EXPLAIN ANALYZE SELECT * FROM test.t1 WHERE gid BETWEEN 15 AND 18;
   ```
   ```
   +-------------------------+-----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------->
   | id                      | estRows   | actRows | task      | access object | execution info                                                                                                        >
   +-------------------------+-----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------->
   | TableReader_7           | 6305.07   | 5035    | root      | partition:p3  | time:27.7ms, loops:7, cop_task: {num: 5, max: 8.65ms, min: 4.08ms, avg: 5.5ms, p95: 8.65ms, max_proc_keys: 10136, p95_>
   | └─Selection_6           | 6305.07   | 5035    | cop[tikv] |               | tikv_task:{proc max:8ms, min:4ms, avg: 5.2ms, p80:8ms, p95:8ms, iters:36, tasks:5}, scan_detail: {total_process_keys: >
   |   └─TableFullScan_5     | 587292.00 | 16664   | cop[tikv] | table:t1      | tikv_task:{proc max:8ms, min:4ms, avg: 4.8ms, p80:8ms, p95:8ms, iters:36, tasks:5}                                    >
   +-------------------------+-----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------->
   ```

   `Q`を押して、`PAGER`ビューを終了します。

5. パーティションとTiKVリージョンの対応を確認します。結果には4つのリージョンが予想されます。

   ```sql
   NOPAGER
   SHOW TABLE test.t1 REGIONS\G
   ```
   ```
   tidb:4000> NOPAGER
   PAGER set to stdout
   tidb:4000> SHOW TABLE test.t1 REGIONS\G
   --------------
   SHOW TABLE test.t1 REGIONS
   --------------
   ...
   *************************** 4. row ***************************
                REGION_ID: 22
                START_KEY: t_343_
                  END_KEY: t_281474976710651_
                LEADER_ID: 262
          LEADER_STORE_ID: 3
                    PEERS: 262
               SCATTERING: 0
            WRITTEN_BYTES: 42
               READ_BYTES: 2132968
     APPROXIMATE_SIZE(MB): 1
         APPROXIMATE_KEYS: 0
   SCHEDULING_CONSTRAINTS: 
         SCHEDULING_STATE: 
   4 rows in set (0.01 sec)
   ```

## 演習 3: リストパーティションテーブル (v6.1.0 以降)
### 概要
+ この演習を通して、リストパーティションテーブルの特性を学びます。
+ まず、モックデータが入力されたリストパーティションテーブルを作成します。次に、特定のクエリの実行計画を分析します。

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

### タスク
1. リストパーティションテーブルを作成します。
2. 実行計画を確認し、さまざまなクエリ述語でのリストパーティションテーブルの動作を観察します。

### 手順
1. TiDBサーバーのシステム変数でリストパーティションテーブルを有効にします。
   ```sql
   SET GLOBAL tidb_enable_list_partition = ON;
   SET SESSION tidb_enable_list_partition = ON;
   ```
   ```
   tidb:4000> SET GLOBAL tidb_enable_list_partition = ON;
   --------------
   SET GLOBAL tidb_enable_list_partition = ON
   --------------

   Query OK, 0 rows affected (0.05 sec)

   tidb:4000> SET SESSION tidb_enable_list_partition = ON;
   --------------
   SET SESSION tidb_enable_list_partition = ON
   --------------

   Query OK, 0 rows affected (0.00 sec)
   ```
   
2. インデックスなしで7つのパーティションを持つリストパーティションテーブル`test.t1`を作成します。`gid`という名前のカラムがリストキーになります。
   
   ```sql
   DROP TABLE IF EXISTS test.t1;
   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY LIST (gid) (
       PARTITION p0 VALUES IN (9),
       PARTITION p1 VALUES IN (10),
       PARTITION p2 VALUES in (5,8),
       PARTITION p3 VALUES IN (6,7),
       PARTITION p4 VALUES IN (12,13),
       PARTITION p5 VALUES IN (11,14),
       PARTITION p6 VALUES IN (0,1,2,3,4,15,16,17,18,19));
   ```
   ```
   tidb:4000> DROP TABLE IF EXISTS test.t1;
   --------------
   DROP TABLE IF EXISTS test.t1
   --------------

   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY LIST (gid) (
       PARTITION p0 VALUES IN (9),
       PARTITION p1 VALUES IN (10),
       PARTITION p2 VALUES in (5,8),
       PARTITION p3 VALUES IN (6,7),
       PARTITION p4 VALUES IN (12,13),
       PARTITION p5 VALUES IN (11,14),
       PARTITION p6 VALUES IN (0,1,2,3,4,15,16,17,18,19));
   Query OK, 0 rows affected (2.05 sec)

   tidb:4000> CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY LIST (gid) (
       ->     PARTITION p0 VALUES IN (9),
       ->     PARTITION p1 VALUES IN (10),
       ->     PARTITION p2 VALUES in (5,8),
       ->     PARTITION p3 VALUES IN (6,7),
       ->     PARTITION p4 VALUES IN (12,13),
       ->     PARTITION p5 VALUES IN (11,14),
       ->     PARTITION p6 VALUES IN (0,1,2,3,4,15,16,17,18,19));
   --------------
   CREATE TABLE test.t1 (rid INT NOT NULL, gid INT NOT NULL) PARTITION BY LIST (gid) (
       PARTITION p0 VALUES IN (9),
       PARTITION p1 VALUES IN (10),
       PARTITION p2 VALUES in (5,8),
       PARTITION p3 VALUES IN (6,7),
       PARTITION p4 VALUES IN (12,13),
       PARTITION p5 VALUES IN (11,14),
       PARTITION p6 VALUES IN (0,1,2,3,4,15,16,17,18,19))
   --------------

   Query OK, 0 rows affected (0.58 sec)
   ```

3. 524288行の`test.t1`テーブルにモックデータを入力し、`gid`に対する行数の分布が以下に表示されている出力と同じであることを確認します。

   ```sql
   SOURCE 07-demo-populate-t1.sql
   SELECT gid, COUNT(*) FROM test.t1 GROUP BY gid ORDER BY 1;
   ```
   ```
   ...
   +-----+----------+
   | gid | COUNT(*) |
   +-----+----------+
   |   0 |        1 |
   |   1 |       19 |
   |   2 |      171 |
   |   3 |      969 |
   |   4 |     3876 |
   |   5 |    11628 |
   |   6 |    27132 |
   |   7 |    50388 |
   |   8 |    75582 |
   |   9 |    92378 |
   |  10 |    92378 |
   |  11 |    75582 |
   |  12 |    50388 |
   |  13 |    27132 |
   |  14 |    11628 |
   |  15 |     3876 |
   |  16 |      969 |
   |  17 |      171 |
   |  18 |       19 |
   |  19 |        1 |
   +-----+----------+
   20 rows in set (0.08 sec)
   ```

4. ステップ1のパーティションスキーマの設計とステップ2の`gid` 分散結果を考慮して、以下のクエリの出力を分析します。パーティション`p0`と`p1`が、それぞれ9と10という1つの値しかカバーしていないのに、行数が最も多い理由を説明できますか。
   ```sql
   SELECT 'P0_COUNT', COUNT(*) FROM test.t1 PARTITION (p0)
   UNION ALL
   SELECT 'P1_COUNT', COUNT(*) FROM test.t1 PARTITION (p1)
   UNION ALL
   SELECT 'P2_COUNT', COUNT(*) FROM test.t1 PARTITION (p2)
   UNION ALL
   SELECT 'P3_COUNT', COUNT(*) FROM test.t1 PARTITION (p3)
   UNION ALL
   SELECT 'P4_COUNT', COUNT(*) FROM test.t1 PARTITION (p4)
   UNION ALL
   SELECT 'P5_COUNT', COUNT(*) FROM test.t1 PARTITION (p5)
   UNION ALL
   SELECT 'P6_COUNT', COUNT(*) FROM test.t1 PARTITION (p6)
   ORDER BY 1;
   ```
   ```
   ...
   +----------+----------+
   | P0_COUNT | COUNT(*) |
   +----------+----------+
   | P0_COUNT |    92378 |
   | P1_COUNT |    92378 |
   | P2_COUNT |    87210 |
   | P3_COUNT |    77520 |
   | P4_COUNT |    77520 |
   | P5_COUNT |    87210 |
   | P6_COUNT |    10072 |
   +----------+----------+
   7 rows in set (0.08 sec)
   ```

## まとめ
`HASH`、`RANGE`、`LIST` パーティショニングに加えて、TiDBは他のさまざまなパーティショニングオプションもサポートしています。詳細については、[TiDBドキュメント](https://docs.pingcap.com/ja/tidb/stable/partitioned-table/)を参照してください。

## 演習終わり