41から始めました

文字通り41歳から始めたブログです。DB(MySQL)を使ってお仕事してるので、DB周りの話を中心に最近始めたこととかをTwitterのノリで書いています。なお、本サイトにおいて示されている見解は私個人の見解であり、所属団体や組織を代表するものではありません。

パーティションほとんどわからんので触ってみた

パーティショニングしたテーブルの確認方法

MySQL触ってて、実は仕事上では一度も触ったことがなかったパーティショニング。

(だって、色んな人が使えないって言ってたんだもん)

だけど、意外と世の中使ってる人は多いので今後のためにもパーティショニングしたテーブルの確認方法を色々見てみました。

まずはパーティションテーブル作る

ドキュメントからテーブルを拝借しました。

パーティションタイプはレンジ、リスト、ハッシュ、キーの4つがあるが、今回はハッシュにしました。 (特に意味はないです。適当に選んだだけです)

mysql [localhost:8020] {admin} (test) > CREATE TABLE ti (
    ->     id INT,
    ->     amount DECIMAL(7 , 2 ),
    ->     tr_date DATE
    -> )  ENGINE=INNODB PARTITION BY HASH (MONTH(tr_date)) PARTITIONS 6;
Query OK, 0 rows affected (0.09 sec)

適当に何件か入れてみる

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (1,
    -> 100,
    -> '2020-01-01');
Query OK, 1 row affected (0.02 sec)

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (1,
    -> 101,
    -> '2020-01-02');
Query OK, 1 row affected (0.01 sec)

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (2,
    -> 200,
    -> '2020-02-02');
Query OK, 1 row affected (0.01 sec)

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (2,
    -> 201,
    -> '2020-02-01');
Query OK, 1 row affected (0.00 sec)

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (3,
    -> 301,
    -> '2020-03-01');
Query OK, 1 row affected (0.00 sec)

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (4,
    -> 400,
    -> '2020-04-01');
Query OK, 1 row affected (0.00 sec)

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (5,
    -> 500,
    -> '2020-05-01');
Query OK, 1 row affected (0.00 sec)

mysql [localhost:8020] {admin} (test) > INSERT INTO `test`.`ti`
    -> (`id`,
    -> `amount`,
    -> `tr_date`)
    -> VALUES
    -> (6,
    -> 600,
    -> '2020-06-01');
Query OK, 1 row affected (0.01 sec)

6件ほど入れてみました。

パーティションテーブルの確認

SHOW CREATE TABLE

SHOW CREATE TABLEではパーティション化されたテーブルの作成に使用されたパーティショニング句を表示します。

mysql [localhost:8020] {admin} (test) > show create table `test`.`ti`\G
*************************** 1. row ***************************
       Table: ti
Create Table: CREATE TABLE `ti` (
  `id` int DEFAULT NULL,
  `amount` decimal(7,2) DEFAULT NULL,
  `tr_date` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY HASH (month(`tr_date`))
PARTITIONS 6 */
1 row in set (0.00 sec)

SHOW TABLE STATUS

SHOW TABLE STATUSではテーブルがパーティション化されているかどうかを判別します。

mysql [localhost:8020] {admin} (test) > show table status like 'ti'\G
*************************** 1. row ***************************
           Name: ti
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 8
 Avg_row_length: 12288
    Data_length: 98304
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2020-06-19 21:31:01
    Update_time: 2020-06-19 21:34:08
     Check_time: NULL
      Collation: utf8mb4_0900_ai_ci
       Checksum: NULL
 Create_options: partitioned
        Comment: 
1 row in set (0.01 sec)

Create_optionsがpartitionedとなっているので、パーティション化されているテーブルです、と。

まあ、ここではただそれだけなんですねw

information_schema.partitions

I_Sのpartitionsビューでも確認できます。 ここではパーティションごとに行が作られますので、先のshow create tableよりも詳細な情報が得られます。

mysql [localhost:8020] {admin} (test) > select * from information_schema.partitions where table_schema = 'test' and table_name = 'ti'\G
*************************** 1. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p0
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 1
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 1
               AVG_ROW_LENGTH: 16384
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 21:31:01
                  UPDATE_TIME: 2020-06-19 21:34:08
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 2. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p1
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 2
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 2
               AVG_ROW_LENGTH: 8192
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 21:31:01
                  UPDATE_TIME: 2020-06-19 21:32:58
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 3. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p2
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 3
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 2
               AVG_ROW_LENGTH: 8192
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 21:31:01
                  UPDATE_TIME: 2020-06-19 21:33:21
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 4. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p3
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 4
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 1
               AVG_ROW_LENGTH: 16384
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 21:31:01
                  UPDATE_TIME: 2020-06-19 21:33:31
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 5. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p4
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 5
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 1
               AVG_ROW_LENGTH: 16384
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 21:31:01
                  UPDATE_TIME: 2020-06-19 21:33:45
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 6. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p5
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 6
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 1
               AVG_ROW_LENGTH: 16384
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 21:31:01
                  UPDATE_TIME: 2020-06-19 21:33:55
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
6 rows in set (0.00 sec)

パーティションのタイプもわかりますし、最後にデータが更新された時間やどのパーティションに何件入ってるかなどもわかりますね。

EXPLAIN

EXPLAINで指定された SELECT によってどのパーティションが使用されているかを確認することができます。

mysql [localhost:8020] {admin} (test) > EXPLAIN select * from `test`.`ti`\G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: ti
   partitions: p0,p1,p2,p3,p4,p5
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.02 sec)

partitions列に作られたパーティションが表示されていますね。

mysql [localhost:8020] {admin} (test) > EXPLAIN select * from `test`.`ti` where tr_date  = '2020-01-01';
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: ti
   partitions: p1
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 2
     filtered: 50.00
        Extra: Using where
1 row in set, 1 warning (0.01 sec)

WHERE句に条件を入れると、使用されたパーティションだけが表示されました。

ALTER TABLE ...COALESCE PARTITION

昔レンジパーティションの記事を読んだときにalter table drop partitionってあったな、と思ったらドキュメント

DROP PARTITION can be used to drop one or more RANGE or LIST partitions. This statement cannot be used with HASH or KEY partitions; instead, use COALESCE PARTITION (see later in this section).

(DROP PARTITIONはRANGE または LIST パーティションでのみ使え、HASH または KEY パーティションに使用することはできません。HASH または KEY パーティションの場合は代わりに COALESCE PARTITION を使用します。)

とあったのでALTER TABLE ...COALESCE PARTITIONでパーティションを減らしました。

ちなみにCOALESCE PARTITION で指定する数字は減らすパーティション数なのでご注意を。

試しにやってみます

mysql [localhost:8020] {admin} (test) > alter table ti drop partition p0;
ERROR 1512 (HY000): DROP PARTITION can only be used on RANGE/LIST partitions

mysql [localhost:8020] {admin} (test) > ALTER TABLE ti COALESCE PARTITION 4;
Query OK, 0 rows affected (0.13 sec)
Records: 0  Duplicates: 0  Warnings: 0

さて、確認してみましょう。

SHOW CREATE TABLE

mysql [localhost:8020] {admin} (test) > show create table `test`.`ti`\G
*************************** 1. row ***************************
       Table: ti
Create Table: CREATE TABLE `ti` (
  `id` int DEFAULT NULL,
  `amount` decimal(7,2) DEFAULT NULL,
  `tr_date` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY HASH (month(`tr_date`))
PARTITIONS 2 */
1 row in set (0.00 sec)

4つ減らしたので2になってます。

SHOW TABLE STATUS

まあ、これは変わりませんねw

mysql [localhost:8020] {admin} (test) > show table status like 'ti'\G
*************************** 1. row ***************************
           Name: ti
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 8
 Avg_row_length: 12288
    Data_length: 98304
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2020-06-19 22:27:58
    Update_time: 2020-06-19 21:34:08
     Check_time: NULL
      Collation: utf8mb4_0900_ai_ci
       Checksum: NULL
 Create_options: partitioned
        Comment: 
1 row in set (0.00 sec)

information_schema.partitions

mysql [localhost:8020] {admin} (test) >  select * from information_schema.partitions where table_schema = 'test' and table_name = 'ti'\G
*************************** 1. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p0
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 1
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 0
               AVG_ROW_LENGTH: 0
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 22:27:58
                  UPDATE_TIME: NULL
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 2. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p1
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 2
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 0
               AVG_ROW_LENGTH: 0
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-19 22:27:58
                  UPDATE_TIME: NULL
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
2 rows in set (0.00 sec)

TABLE_ROWSが0になってますね・・・

ドキュメントには

The data contained in the last number partitions will be merged into the remaining partitions. In this case, partitions 4 and 5 will be merged into the first 4 partitions (the partitions numbered 0, 1, 2, and 3).

とあるんで、これらに入ると思ったんですがふっとんだんでしょうか?

mysql [localhost:8020] {admin} (test) > select * from ti;
+------+--------+------------+
| id   | amount | tr_date    |
+------+--------+------------+
|    6 | 600.00 | 2020-06-01 |
|    2 | 200.00 | 2020-02-02 |
|    2 | 201.00 | 2020-02-01 |
|    4 | 400.00 | 2020-04-01 |
|    1 | 100.00 | 2020-01-01 |
|    1 | 101.00 | 2020-01-02 |
|    3 | 301.00 | 2020-03-01 |
|    5 | 500.00 | 2020-05-01 |
+------+--------+------------+
8 rows in set (0.00 sec)

ありますねえ…。

この後、再起動したり、データ入れてみたりしましたが、今まで入ってた分はTABLE_ROWSに戻らず。

EXPLAIN

(root@localhost) [test]> EXPLAIN select * from `test`.`ti`\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: ti
   partitions: p0,p1
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.02 sec)

partitionsはp0,p1 だけになってますね。

こちらもrowsが1(試しに後から入れた1件)のみ…。

どうしても行数を復活させたい

というわけで試すことにしました。

ALTER TABLE ... REBUILD PARTITION;

ALTER TABLE ... REBUILD PARTITIONでパーティションを再構築してみます。

ドキュメントでは

Rebuilds the partition; this has the same effect as dropping all records stored in the partition, then reinserting them. This can be useful for purposes of defragmentation.

パーティションに格納されているすべてのレコードを削除してからそれらを再度挿入することと同じ効果があります。これはデフラグに役立つことがあります。)

とあるので、再構築すれば読めるようになるのでは?

(root@localhost) [test]> alter table ti rebuild partition p0,p1;
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0
(root@localhost) [test]> select * from information_schema.partitions where table_schema = 'test' and table_name = 'ti'\G
*************************** 1. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p1
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 2
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 0
               AVG_ROW_LENGTH: 0
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-20 08:47:54
                  UPDATE_TIME: NULL
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 2. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p0
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 1
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 0
               AVG_ROW_LENGTH: 0
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-20 08:47:54
                  UPDATE_TIME: NULL
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
2 rows in set (0.01 sec)

残念、再構築では入りませんでした。

ALTER TABLE ... OPTIMIZE PARTITION

次にパーティションの最適化をやってみます。

ドキュメントでは

ALTER TABLE ... OPTIMIZE PARTITION を使用して、未使用領域を解放したりパーティションデータファイルをデフラグしたりできます。 (パーティションから多数の行を削除した場合、または可変長行を持つ (つまり、VARCHAR、BLOB、または TEXT カラムを持つ) パーティション化されたテーブルに多くの変更を行なった場合は、 ALTER TABLE ... OPTIMIZE PARTITION を使用して、未使用領域を解放したりパーティションデータファイルをデフラグしたりできます。)

とあるので、少しイメージと違うような気持ちもしますが試してみましょう。

(root@localhost) [test]> ALTER TABLE ti OPTIMIZE PARTITION p0, p1;
+---------+----------+----------+---------------------------------------------------------------------------------------------+
| Table   | Op       | Msg_type | Msg_text                                                                                    |
+---------+----------+----------+---------------------------------------------------------------------------------------------+
| test.ti | optimize | note     | Table does not support optimize on partitions. All partitions will be rebuilt and analyzed. |
| test.ti | optimize | status   | OK                                                                                          |
+---------+----------+----------+---------------------------------------------------------------------------------------------+
2 rows in set (0.08 sec)

1パーティションに対してはできないよ!という注意が見えますが、ちゃんと全パーティションを選択しているのでOKとなってます。

(root@localhost) [test]> select * from information_schema.partitions where table_schema = 'test' and table_name = 'ti'\G
*************************** 1. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p1
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 2
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 5
               AVG_ROW_LENGTH: 3276
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-20 08:48:16
                  UPDATE_TIME: NULL
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
*************************** 2. row ***************************
                TABLE_CATALOG: def
                 TABLE_SCHEMA: test
                   TABLE_NAME: ti
               PARTITION_NAME: p0
            SUBPARTITION_NAME: NULL
   PARTITION_ORDINAL_POSITION: 1
SUBPARTITION_ORDINAL_POSITION: NULL
             PARTITION_METHOD: HASH
          SUBPARTITION_METHOD: NULL
         PARTITION_EXPRESSION: month(`tr_date`)
      SUBPARTITION_EXPRESSION: NULL
        PARTITION_DESCRIPTION: NULL
                   TABLE_ROWS: 4
               AVG_ROW_LENGTH: 4096
                  DATA_LENGTH: 16384
              MAX_DATA_LENGTH: 0
                 INDEX_LENGTH: 0
                    DATA_FREE: 0
                  CREATE_TIME: 2020-06-20 08:48:16
                  UPDATE_TIME: NULL
                   CHECK_TIME: NULL
                     CHECKSUM: NULL
            PARTITION_COMMENT: 
                    NODEGROUP: default
              TABLESPACE_NAME: NULL
2 rows in set (0.00 sec)

おお、TABLE_ROWSが見事に見えるようになりました。

正解はOPTIMIZE PARTITIONだったようです。

(root@localhost) [test]> EXPLAIN select * from `test`.`ti`\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: ti
   partitions: p0,p1
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 9
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)

EXPLAINでもrowsが 9に見えてます。

最後に

今日はパーティションと少し戯れてみました。

パーティションの数変更した後に確認しようとしたときに行数が狂っちゃう(0になっちゃう)のはイケてないと思うんだけど、直し方はありました。

(バグ登録されてるのかな?あとで見てみよう)

まだ触りたてなので、他の3つのパーティションタイプやそれぞれでのALTER TABLE ... ANALYZE PARTITION、CHECK PARTITION、REPAIR PARTITION、REMOVE PARTITIONINGあたりも触ってないのでそのへんも気が向いたら手を出していきます。

(でも、そもそも使うとしたらみなさんレンジやリストのタイプなのかしら?)

あ、あと、MySQL5.6ではEXPLAINではなくて、EXPLAIN PARTITIONSなのでお間違えなく

(root@127.0.0.1) [test]> EXPLAIN PARTITIONS select * from ti\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: ti
   partitions: p0,p1,p2,p3,p4,p5
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 6
        Extra: NULL
1 row in set (0.00 sec)

参考

dev.mysql.com

dev.mysql.com

dev.mysql.com