CLOVER🍀

That was when it all began.

TiDB(TiKV)のキーのエンコード・デコード結果を確認する

これは、なにをしたくて書いたもの?

前に、TiDB(TiKV)のデータのリージョンごとの配置状況を確認してみました。

TiDB(TiKV)のデータのリージョンごとの配置状況を確認してみる - CLOVER🍀

この時、複合主キーにしたパターンでSTART_KEYEND_KEYがよくわからない表示になったので、このあたりをもう少し
確認できないかな?ということで。

結果としては詳しくはわからなかったのですが、確認したことをメモしておきます。

データのリージョンごとの配置状況を確認する方法

おさらい的に。データがリージョンごとにどのように配置されるのかを確認するには、START_KEYEND_KEYを見るのがよいのですが、
これはshow table [テーブル名] regionsで得られます。

SHOW TABLE REGIONS | PingCAP Docs

また、表示形式は変わりますがinformation_schemaのtikv_region_statusテーブルからも得ることができます。

TIKV_REGION_STATUS | PingCAP Docs

キーをデコードする

このキーの値をデコードして確認には、TIDB_DECODE_KEY関数を使うとよさそうです。

TiDB Specific Functions | PingCAP Docs

一方で、エンコードについてはこちらに説明があります。

TiDB Computing / Mapping table data to Key-Value

キーはtablePrefix{TableID}_recordPrefixSep{RowID}という形式でエンコードされます。

前回のエントリーで、たとえばSTART_KEYとしてt_106_r_207740といった値が得られていましたが、このフォーマットですね。

TiDB(TiKV)のデータのリージョンごとの配置状況を確認してみる - CLOVER🍀

実際のイメージは、こちらが参考になるでしょう。

TiDB Computing / Mapping table data to Key-Value / Example of Key-Value mapping relationship

ここでRowIDはテーブルの主キーが整数型であれば主キーの値がそのまま使われ、そうでない場合はテーブル内で一意の整数値が割り当てられる
そうです。この値をどうやって算出しているのか確認したかったのですが、そこまではわかりませんでした…。

今回は、いくつかのパターンのテーブルを用意してSTART_KEYEND_KEYの変化を見ていってみたいと思います。

環境

今回の環境はこちら。

$ tiup --version
1.16.0 v1.16.0-nightly-2
Go Version: go1.21.12
Git Ref: master
GitHash: bac3c2e61555ab6dd2b69ad18bc01cf8dfb7e700

使用するMySQLクライアント。

$ mysql --version
mysql  Ver 8.0.38 for Linux on x86_64 (MySQL Community Server - GPL)

TiDBのバージョン。

mysql> select version();
+--------------------+
| version()          |
+--------------------+
| 8.0.11-TiDB-v8.1.0 |
+--------------------+
1 row in set (0.00 sec)

TiDBは以下のコマンドで起動しているものとします。

$ tiup playground v8.1.0 --host 0.0.0.0

また、TiDBへの接続は以下のコマンドで行うこととします。

$ mysql -uroot -h127.0.0.1 -P4000 --local-infile=1

用意するテーブルとデータ

テーブルは、次の4パターンを作成することにします。

主キーがひとつのinteger型のテーブル。

create table integer_single_id(
  id1 integer,
  id2 integer,
  primary key(id1)
);

主キーが2つのinteger型のテーブル。

create table integer_multiple_ids(
  id1 integer,
  id2 integer,
  primary key(id1, id2)
);

主キーがひとつのvarchar型のテーブル。

create table varchar_single_id(
  id1 varchar(10),
  id2 varchar(10),
  primary key(id1)
);

主キーが2つのvarchar型のテーブル。

create table varchar_multiple_ids(
  id1 varchar(10),
  id2 varchar(10),
  primary key(id1, id2)
);

データベースはtestを使います。

use test;

登録するデータはこのようにして作成。

$ for i in $(seq 1 1000000); do echo "$i,$i"; done > ids.csv

見ればわかりますが、できあがるのはこんなデータです。

$ head ids.csv
1,1
2,2
3,3
4,4
5,5
6,6
7,7
8,8
9,9
10,10

$ tail ids.csv
999991,999991
999992,999992
999993,999993
999994,999994
999995,999995
999996,999996
999997,999997
999998,999998
999999,999999
1000000,1000000

このデータを登録します。

load data local infile 'ids.csv' into table integer_single_id
  fields terminated by ','
  lines terminated by '\n'
(id1, id2);


load data local infile 'ids.csv' into table integer_multiple_ids
  fields terminated by ','
  lines terminated by '\n'
(id1, id2);


load data local infile 'ids.csv' into table varchar_single_id
  fields terminated by ','
  lines terminated by '\n'
(id1, id2);


load data local infile 'ids.csv' into table varchar_multiple_ids
  fields terminated by ','
  lines terminated by '\n'
(id1, id2);

このデータを使って確認していきます。

主キーがひとつのinteger型のテーブルの場合

まずは主キーがひとつのinteger型のテーブルから。show table [テーブル名] regionsを見てみます。

mysql> show table integer_single_id regions\G
*************************** 1. row ***************************
             REGION_ID: 171
             START_KEY: t_104_
               END_KEY: t_104_r_289331
             LEADER_ID: 172
       LEADER_STORE_ID: 1
                 PEERS: 172
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 17294139
  APPROXIMATE_SIZE(MB): 59
      APPROXIMATE_KEYS: 510351
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 2. row ***************************
             REGION_ID: 165
             START_KEY: t_104_r_289331
               END_KEY: t_106_
             LEADER_ID: 166
       LEADER_STORE_ID: 1
                 PEERS: 166
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 42640200
  APPROXIMATE_SIZE(MB): 86
      APPROXIMATE_KEYS: 1002167
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
2 rows in set (0.02 sec)

RowIDが主キーの値になっていることが確認できます。

information_schemaスキーマtikv_region_statusテーブル。

mysql> select * from information_schema.tikv_region_status where db_name = 'test' and table_name = 'integer_single_id' order by region_id asc\G
*************************** 1. row ***************************
                REGION_ID: 165
                START_KEY: 7480000000000000FF685F728000000000FF046A330000000000FA
                  END_KEY: 7480000000000000FF6A00000000000000F8
                 TABLE_ID: 104
                  DB_NAME: test
               TABLE_NAME: integer_single_id
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 61
            WRITTEN_BYTES: 0
               READ_BYTES: 85281135
         APPROXIMATE_SIZE: 86
         APPROXIMATE_KEYS: 1002167
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 2. row ***************************
                REGION_ID: 171
                START_KEY: 7480000000000000FF6800000000000000F8
                  END_KEY: 7480000000000000FF685F728000000000FF046A330000000000FA
                 TABLE_ID: 104
                  DB_NAME: test
               TABLE_NAME: integer_single_id
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 61
            WRITTEN_BYTES: 0
               READ_BYTES: 34588733
         APPROXIMATE_SIZE: 59
         APPROXIMATE_KEYS: 510351
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
2 rows in set (0.14 sec)

キーをtidb_decode_key関数でデコードしてみます。

mysql> select start_key, tidb_decode_key(start_key) as decoded_start_key, end_key, tidb_decode_key(end_key) as decoded_end_key from information_schema.tikv_region_status where table_name='integer_single_id'\G
*************************** 1. row ***************************
        start_key: 7480000000000000FF6800000000000000F8
decoded_start_key: {"table_id":104}
          end_key: 7480000000000000FF685F728000000000FF046A330000000000FA
  decoded_end_key: {"id1":289331,"table_id":"104"}
*************************** 2. row ***************************
        start_key: 7480000000000000FF685F728000000000FF046A330000000000FA
decoded_start_key: {"id1":289331,"table_id":"104"}
          end_key: 7480000000000000FF6A00000000000000F8
  decoded_end_key: {"table_id":106}
2 rows in set (0.02 sec)

show table [テーブル名] regionsの結果と同じ内容になりましたね。

ちなみに、整形したクエリーはこうです。

select
  *
from
  information_schema.tikv_region_status
where
  db_name = 'test'
  and table_name = 'integer_single_id'
order by
  region_id asc\G


select
  start_key,
  tidb_decode_key(start_key) as decoded_start_key,
  end_key,
  tidb_decode_key(end_key) as decoded_end_key
from
  information_schema.tikv_region_status
where
  table_name='integer_single_id'\G

主キーが2つのinteger型のテーブルの場合

次は主キーが2つのinteger型のテーブルの場合。

mysql> show table integer_multiple_ids regions\G
*************************** 1. row ***************************
             REGION_ID: 173
             START_KEY: t_106_
               END_KEY: t_106_r_03800000000002cec603800000000002cec6
             LEADER_ID: 174
       LEADER_STORE_ID: 1
                 PEERS: 174
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 21
      APPROXIMATE_KEYS: 0
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 2. row ***************************
             REGION_ID: 175
             START_KEY: t_106_r_03800000000002cec603800000000002cec6
               END_KEY: t_106_r_038000000000097c49038000000000097c49
             LEADER_ID: 176
       LEADER_STORE_ID: 1
                 PEERS: 176
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 57
      APPROXIMATE_KEYS: 450513
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 3. row ***************************
             REGION_ID: 167
             START_KEY: t_106_r_038000000000097c49038000000000097c49
               END_KEY: t_108_
             LEADER_ID: 168
       LEADER_STORE_ID: 1
                 PEERS: 168
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 70
      APPROXIMATE_KEYS: 776181
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
3 rows in set (0.02 sec)

今度は単純に主キーの値、というわけにはいかなくなりましたね。

ここで、START_KEYt_106_r_03800000000002cec603800000000002cec6の値をよく見てみます。

03800000000002cec603800000000002cec6の部分ですが、03800000000002cec6の繰り返しになっていますね。今回は主キーの値を
同じにしているので、どうやら主キーの値をもとに計算していそうな感じはします。

どうやって計算しているかはわかりませんが…。

information_schemaスキーマtikv_region_statusテーブル。

mysql> select * from information_schema.tikv_region_status where db_name = 'test' and table_name = 'integer_multiple_ids' order by region_id asc\G
*************************** 1. row ***************************
                REGION_ID: 167
                START_KEY: 7480000000000000FF6A5F720380000000FF00097C4903800000FF0000097C49000000FC
                  END_KEY: 7480000000000000FF6C00000000000000F8
                 TABLE_ID: 106
                  DB_NAME: test
               TABLE_NAME: integer_multiple_ids
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 63
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 70
         APPROXIMATE_KEYS: 776181
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 2. row ***************************
                REGION_ID: 173
                START_KEY: 7480000000000000FF6A00000000000000F8
                  END_KEY: 7480000000000000FF6A5F720380000000FF0002CEC603800000FF000002CEC6000000FC
                 TABLE_ID: 106
                  DB_NAME: test
               TABLE_NAME: integer_multiple_ids
                 IS_INDEX: 1
                 INDEX_ID: 1
               INDEX_NAME: PRIMARY
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 62
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 21
         APPROXIMATE_KEYS: 0
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 3. row ***************************
                REGION_ID: 173
                START_KEY: 7480000000000000FF6A00000000000000F8
                  END_KEY: 7480000000000000FF6A5F720380000000FF0002CEC603800000FF000002CEC6000000FC
                 TABLE_ID: 106
                  DB_NAME: test
               TABLE_NAME: integer_multiple_ids
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 62
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 21
         APPROXIMATE_KEYS: 0
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 4. row ***************************
                REGION_ID: 175
                START_KEY: 7480000000000000FF6A5F720380000000FF0002CEC603800000FF000002CEC6000000FC
                  END_KEY: 7480000000000000FF6A5F720380000000FF00097C4903800000FF0000097C49000000FC
                 TABLE_ID: 106
                  DB_NAME: test
               TABLE_NAME: integer_multiple_ids
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 63
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 57
         APPROXIMATE_KEYS: 450513
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
4 rows in set (0.02 sec)

たとえば7480000000000000FF6A5F720380000000FF0002CEC603800000FF000002CEC6000000FCを見ても、同じ値の繰り返しに
なっているわけではなさそうですね…。ちょっと読み解けないです。

デコードはできるのでしょうか?

tidb_decode_key関数でデコード。

mysql> select start_key, tidb_decode_key(start_key) as decoded_start_key, end_key, tidb_decode_key(end_key) as decoded_end_key from information_schema.tikv_region_status where table_name='integer_multiple_ids'\G
*************************** 1. row ***************************
        start_key: 7480000000000000FF6A5F720380000000FF00097C4903800000FF0000097C49000000FC
decoded_start_key: {"handle":{"id1":"621641","id2":"621641"},"table_id":106}
          end_key: 7480000000000000FF6C00000000000000F8
  decoded_end_key: {"table_id":108}
*************************** 2. row ***************************
        start_key: 7480000000000000FF6A5F720380000000FF0002CEC603800000FF000002CEC6000000FC
decoded_start_key: {"handle":{"id1":"184006","id2":"184006"},"table_id":106}
          end_key: 7480000000000000FF6A5F720380000000FF00097C4903800000FF0000097C49000000FC
  decoded_end_key: {"handle":{"id1":"621641","id2":"621641"},"table_id":106}
*************************** 3. row ***************************
        start_key: 7480000000000000FF6A00000000000000F8
decoded_start_key: {"table_id":106}
          end_key: 7480000000000000FF6A5F720380000000FF0002CEC603800000FF000002CEC6000000FC
  decoded_end_key: {"handle":{"id1":"184006","id2":"184006"},"table_id":106}
*************************** 4. row ***************************
        start_key: 7480000000000000FF6A00000000000000F8
decoded_start_key: {"table_id":106}
          end_key: 7480000000000000FF6A5F720380000000FF0002CEC603800000FF000002CEC6000000FC
  decoded_end_key: {"handle":{"id1":"184006","id2":"184006"},"table_id":106}
4 rows in set (0.01 sec)

できましたね。それぞれの主キーの値がデコードできています。

主キーがひとつのvarchar型のテーブル

主キーがひとつのvarchar型のテーブルの場合。

show table [テーブル名] regions

mysql> show table varchar_single_id regions\G
*************************** 1. row ***************************
             REGION_ID: 179
             START_KEY: t_108_
               END_KEY: t_108_r_013233393333300000fd
             LEADER_ID: 180
       LEADER_STORE_ID: 1
                 PEERS: 180
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 32
      APPROXIMATE_KEYS: 183108
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 2. row ***************************
             REGION_ID: 177
             START_KEY: t_108_r_013233393333300000fd
               END_KEY: t_108_r_013433383930000000fc
             LEADER_ID: 178
       LEADER_STORE_ID: 1
                 PEERS: 178
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 44
      APPROXIMATE_KEYS: 258717
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 3. row ***************************
             REGION_ID: 181
             START_KEY: t_108_r_013433383930000000fc
               END_KEY: t_108_r_013533313936300000fd
             LEADER_ID: 182
       LEADER_STORE_ID: 1
                 PEERS: 182
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 10
      APPROXIMATE_KEYS: 0
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 4. row ***************************
             REGION_ID: 183
             START_KEY: t_108_r_013533313936300000fd
               END_KEY: t_108_r_013833363239360000fd
             LEADER_ID: 184
       LEADER_STORE_ID: 1
                 PEERS: 184
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 79
      APPROXIMATE_KEYS: 451587
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 5. row ***************************
             REGION_ID: 169
             START_KEY: t_108_r_013833363239360000fd
               END_KEY: t_110_
             LEADER_ID: 170
       LEADER_STORE_ID: 1
                 PEERS: 170
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 18
      APPROXIMATE_KEYS: 157119
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
5 rows in set (0.02 sec)

こちらも主キーの値がそのまま使われているわけではなさそうです。

information_schemaスキーマtikv_region_statusテーブル。

mysql> select * from information_schema.tikv_region_status where db_name = 'test' and table_name = 'varchar_single_id' order by region_id asc\G
*************************** 1. row ***************************
                REGION_ID: 169
                START_KEY: 7480000000000000FF6C5F720138333632FF39360000FD000000FC
                  END_KEY: 7480000000000000FF6E00000000000000F8
                 TABLE_ID: 108
                  DB_NAME: test
               TABLE_NAME: varchar_single_id
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 65
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 18
         APPROXIMATE_KEYS: 157119
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 2. row ***************************
                REGION_ID: 177
                START_KEY: 7480000000000000FF6C5F720132333933FF33300000FD000000FC
                  END_KEY: 7480000000000000FF6C5F720134333839FF30000000FC000000FC
                 TABLE_ID: 108
                  DB_NAME: test
               TABLE_NAME: varchar_single_id
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 44
         APPROXIMATE_KEYS: 258717
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 3. row ***************************
                REGION_ID: 179
                START_KEY: 7480000000000000FF6C00000000000000F8
                  END_KEY: 7480000000000000FF6C5F720132333933FF33300000FD000000FC
                 TABLE_ID: 108
                  DB_NAME: test
               TABLE_NAME: varchar_single_id
                 IS_INDEX: 1
                 INDEX_ID: 1
               INDEX_NAME: PRIMARY
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 32
         APPROXIMATE_KEYS: 183108
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 4. row ***************************
                REGION_ID: 179
                START_KEY: 7480000000000000FF6C00000000000000F8
                  END_KEY: 7480000000000000FF6C5F720132333933FF33300000FD000000FC
                 TABLE_ID: 108
                  DB_NAME: test
               TABLE_NAME: varchar_single_id
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 32
         APPROXIMATE_KEYS: 183108
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 5. row ***************************
                REGION_ID: 181
                START_KEY: 7480000000000000FF6C5F720134333839FF30000000FC000000FC
                  END_KEY: 7480000000000000FF6C5F720135333139FF36300000FD000000FC
                 TABLE_ID: 108
                  DB_NAME: test
               TABLE_NAME: varchar_single_id
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 10
         APPROXIMATE_KEYS: 0
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 6. row ***************************
                REGION_ID: 183
                START_KEY: 7480000000000000FF6C5F720135333139FF36300000FD000000FC
                  END_KEY: 7480000000000000FF6C5F720138333632FF39360000FD000000FC
                 TABLE_ID: 108
                  DB_NAME: test
               TABLE_NAME: varchar_single_id
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 65
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 79
         APPROXIMATE_KEYS: 451587
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
6 rows in set (0.01 sec)

tidb_decode_key関数でデコード。

mysql> select start_key, tidb_decode_key(start_key) as decoded_start_key, end_key, tidb_decode_key(end_key) as decoded_end_key from information_schema.tikv_region_status where table_name='varchar_single_id'\G
*************************** 1. row ***************************
        start_key: 7480000000000000FF6C00000000000000F8
decoded_start_key: {"table_id":108}
          end_key: 7480000000000000FF6C5F720132333933FF33300000FD000000FC
  decoded_end_key: {"handle":{},"table_id":108}
*************************** 2. row ***************************
        start_key: 7480000000000000FF6C00000000000000F8
decoded_start_key: {"table_id":108}
          end_key: 7480000000000000FF6C5F720132333933FF33300000FD000000FC
  decoded_end_key: {"handle":{},"table_id":108}
*************************** 3. row ***************************
        start_key: 7480000000000000FF6C5F720138333632FF39360000FD000000FC
decoded_start_key: {"handle":{},"table_id":108}
          end_key: 7480000000000000FF6E00000000000000F8
  decoded_end_key: {"table_id":110}
*************************** 4. row ***************************
        start_key: 7480000000000000FF6C5F720135333139FF36300000FD000000FC
decoded_start_key: {"handle":{},"table_id":108}
          end_key: 7480000000000000FF6C5F720138333632FF39360000FD000000FC
  decoded_end_key: {"handle":{},"table_id":108}
*************************** 5. row ***************************
        start_key: 7480000000000000FF6C5F720134333839FF30000000FC000000FC
decoded_start_key: {"handle":{},"table_id":108}
          end_key: 7480000000000000FF6C5F720135333139FF36300000FD000000FC
  decoded_end_key: {"handle":{},"table_id":108}
*************************** 6. row ***************************
        start_key: 7480000000000000FF6C5F720132333933FF33300000FD000000FC
decoded_start_key: {"handle":{},"table_id":108}
          end_key: 7480000000000000FF6C5F720134333839FF30000000FC000000FC
  decoded_end_key: {"handle":{},"table_id":108}
6 rows in set (0.02 sec)

中身がわかりませんね…。

主キーが2つのvarchar型のテーブル

最後は主キーが2つのvarchar型のテーブルです。

show table [テーブル名] regions

mysql> show table varchar_multiple_ids regions\G
*************************** 1. row ***************************
             REGION_ID: 187
             START_KEY: t_110_
               END_KEY: t_110_r_013232363937330000fd013232363937330000fd
             LEADER_ID: 188
       LEADER_STORE_ID: 1
                 PEERS: 188
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 16
      APPROXIMATE_KEYS: 0
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 2. row ***************************
             REGION_ID: 185
             START_KEY: t_110_r_013232363937330000fd013232363937330000fd
               END_KEY: t_110_r_013430343530000000fc013430343530000000fc
             LEADER_ID: 186
       LEADER_STORE_ID: 1
                 PEERS: 186
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 34
      APPROXIMATE_KEYS: 86080
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 3. row ***************************
             REGION_ID: 189
             START_KEY: t_110_r_013430343530000000fc013430343530000000fc
               END_KEY: t_110_r_013935353830300000fd013935353830300000fd
             LEADER_ID: 190
       LEADER_STORE_ID: 1
                 PEERS: 190
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 99
      APPROXIMATE_KEYS: 680540
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
*************************** 4. row ***************************
             REGION_ID: 54
             START_KEY: t_110_r_013935353830300000fd013935353830300000fd
               END_KEY: t_281474976710649_
             LEADER_ID: 55
       LEADER_STORE_ID: 1
                 PEERS: 55
            SCATTERING: 0
         WRITTEN_BYTES: 0
            READ_BYTES: 0
  APPROXIMATE_SIZE(MB): 13
      APPROXIMATE_KEYS: 31677
SCHEDULING_CONSTRAINTS:
      SCHEDULING_STATE:
4 rows in set (0.00 sec)

複合主キーもやっぱりわかりませんね。

このうちのひとつ、t_110_r_013232363937330000fd013232363937330000fdという値を分解してみると013232363937330000fd
繰り返しになっていることは確認できるので、主キーの値が元になっているのはこちらも同じようです。

information_schemaスキーマtikv_region_statusテーブル。

mysql> select * from information_schema.tikv_region_status where db_name = 'test' and table_name = 'varchar_multiple_ids' order by region_id asc\G
*************************** 1. row ***************************
                REGION_ID: 54
                START_KEY: 7480000000000000FF6E5F720139353538FF30300000FD013935FF353830300000FD00FE
                  END_KEY: 748000FFFFFFFFFFFFF900000000000000F8
                 TABLE_ID: 110
                  DB_NAME: test
               TABLE_NAME: varchar_multiple_ids
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 13
         APPROXIMATE_KEYS: 31677
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 2. row ***************************
                REGION_ID: 185
                START_KEY: 7480000000000000FF6E5F720132323639FF37330000FD013232FF363937330000FD00FE
                  END_KEY: 7480000000000000FF6E5F720134303435FF30000000FC013430FF343530000000FC00FE
                 TABLE_ID: 110
                  DB_NAME: test
               TABLE_NAME: varchar_multiple_ids
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 34
         APPROXIMATE_KEYS: 86080
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 3. row ***************************
                REGION_ID: 187
                START_KEY: 7480000000000000FF6E00000000000000F8
                  END_KEY: 7480000000000000FF6E5F720132323639FF37330000FD013232FF363937330000FD00FE
                 TABLE_ID: 110
                  DB_NAME: test
               TABLE_NAME: varchar_multiple_ids
                 IS_INDEX: 1
                 INDEX_ID: 1
               INDEX_NAME: PRIMARY
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 16
         APPROXIMATE_KEYS: 0
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 4. row ***************************
                REGION_ID: 187
                START_KEY: 7480000000000000FF6E00000000000000F8
                  END_KEY: 7480000000000000FF6E5F720132323639FF37330000FD013232FF363937330000FD00FE
                 TABLE_ID: 110
                  DB_NAME: test
               TABLE_NAME: varchar_multiple_ids
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 16
         APPROXIMATE_KEYS: 0
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
*************************** 5. row ***************************
                REGION_ID: 189
                START_KEY: 7480000000000000FF6E5F720134303435FF30000000FC013430FF343530000000FC00FE
                  END_KEY: 7480000000000000FF6E5F720139353538FF30300000FD013935FF353830300000FD00FE
                 TABLE_ID: 110
                  DB_NAME: test
               TABLE_NAME: varchar_multiple_ids
                 IS_INDEX: 0
                 INDEX_ID: NULL
               INDEX_NAME: NULL
             IS_PARTITION: 0
             PARTITION_ID: NULL
           PARTITION_NAME: NULL
           EPOCH_CONF_VER: 1
            EPOCH_VERSION: 64
            WRITTEN_BYTES: 0
               READ_BYTES: 0
         APPROXIMATE_SIZE: 99
         APPROXIMATE_KEYS: 680540
  REPLICATIONSTATUS_STATE: NULL
REPLICATIONSTATUS_STATEID: NULL
5 rows in set (0.01 sec)

tidb_decode_key関数でデコード。

mysql> select start_key, tidb_decode_key(start_key) as decoded_start_key, end_key, tidb_decode_key(end_key) as decoded_end_key from information_schema.tikv_region_status where table_name='varchar_multiple_ids'\G
*************************** 1. row ***************************
        start_key: 7480000000000000FF6E5F720132323639FF37330000FD013232FF363937330000FD00FE
decoded_start_key: {"handle":{},"table_id":110}
          end_key: 7480000000000000FF6E5F720134303435FF30000000FC013430FF343530000000FC00FE
  decoded_end_key: {"handle":{},"table_id":110}
*************************** 2. row ***************************
        start_key: 7480000000000000FF6E5F720134303435FF30000000FC013430FF343530000000FC00FE
decoded_start_key: {"handle":{},"table_id":110}
          end_key: 7480000000000000FF6E5F720139353538FF30300000FD013935FF353830300000FD00FE
  decoded_end_key: {"handle":{},"table_id":110}
*************************** 3. row ***************************
        start_key: 7480000000000000FF6E00000000000000F8
decoded_start_key: {"table_id":110}
          end_key: 7480000000000000FF6E5F720132323639FF37330000FD013232FF363937330000FD00FE
  decoded_end_key: {"handle":{},"table_id":110}
*************************** 4. row ***************************
        start_key: 7480000000000000FF6E00000000000000F8
decoded_start_key: {"table_id":110}
          end_key: 7480000000000000FF6E5F720132323639FF37330000FD013232FF363937330000FD00FE
  decoded_end_key: {"handle":{},"table_id":110}
*************************** 5. row ***************************
        start_key: 7480000000000000FF6E5F720139353538FF30300000FD013935FF353830300000FD00FE
decoded_start_key: {"handle":{},"table_id":110}
          end_key: 748000FFFFFFFFFFFFF900000000000000F8
  decoded_end_key: {"table_id":281474976710649}
5 rows in set (0.01 sec)

やっぱりこちらもわかりません。

確認はこんなところにしておきます…。

おわりに

TiDB(TiKV)のキーのエンコード・デコードを確認してみました。

ドキュメントにあるとおり、主キーが整数型の時はきわめてわかりやすい結果になるのですが、複合主キーになったりそれ以外の型に
なったりするとどういう計算になっているのかよくわからなくなりますね。

最終的にRowIDという整数値になっているようなのですが、計算方法はドキュメントに書かれていないので。
ソースコードも見てみたのですが、今回は追いきれませんでした…。

ただ、主キーの値がもとになっていることはshow table [テーブル名] regionsの結果から、なんとなく読み取れたような気がします。

データの配置はTiDB任せになるので、今回の掘り下げはこのくらいにしておきましょう。