DumplingによるMySQL/TiDBからの高速Export

## はじめに

[Dumpling]() はPingCAPが作成しているダンプツールで、MySQLやTiDBのデータをcsvやsqlの形式で出力することができます。mysqldumpにない特徴を備え、高速、柔軟な出力を可能としているのが特徴です。

本記事では、Dumplingの使い方について説明します。Dumplingのオプションは非常に豊富なので、よくあるユースケースを挙げてオプションを見ていきたいと思います。

## Dumplingの特徴

- パラレルエクスポートが可能
- S3やGCSといったクラウドストレージに直接出力可能
- 出力条件をwhere指定やselect文指定という形で柔軟に指定できる
- 出力ファイルを圧縮可能
- 出力ファイルを一定サイズで分割可能

## Dumplingのインストール

https://docs.pingcap.com/ja/tidb/stable/dumpling-overview

DumplingはTiUPを利用してインストールできます。単独のコマンドとしてもインストール可能なのでお好きな方を選んでください。

```bash
tiup install dumpling
```

## Dumplingのユースケース

Dumplingのユースケースを利用例とともに見ていきましょう。なお、Dumpling元のMySQLは下記の記事で使ったEmployeeデータベースをimportしているものを想定しています。

https://qiita.com/bohnen/items/7849d1e1b15bba067275

### MySQLからデータのエクスポート (TiDB移行用）

全量のデータ移行は[DM](https://docs.pingcap.com/ja/tidb/stable/dm-overview)といった他のツールもあるのですが、Dumplingを使うと一旦データをテキストの形で書き出すので修正ができるというメリットもあります。

```bash
tiup dumpling -h 127.0.0.1 -P 3306 -u root -p <password> \
-B employees -o output/ --filetype sql
```

#### オプションの解説

- -h ホストを指定
- -P ポートを指定。DumplingはTiDBのツールなのでデフォルトは4000
- -u ユーザーを指定
- -p パスワードを指定
- -B エクスポートするデータベースを指定
- -o 出力ディレクトリを指定
- --filetype 出力ファイル形式を指定。デフォルトはsqlだがなんだっけってなるので常に書いてる

#### 出力例

出力は下記の例のようになります。TiDBのLightningやTiDB CloudのImportで読み込める形式で出力されますが、sqlを順に実行すればMySQLでも実行可能です。

```bash
Permissions Size User   Date Modified Name
.rw-rw-r--   199 bohnen 15 12月 17:05  employees-schema-create.sql
.rw-rw-r--   295 bohnen 15 12月 17:05  employees.departments-schema.sql
.rw-rw-r--   315 bohnen 15 12月 17:05  employees.departments.000000000.sql
.rw-rw-r--   553 bohnen 15 12月 17:05  employees.dept_emp-schema.sql
.rw-rw-r--   14M bohnen 15 12月 17:05  employees.dept_emp.000000000.sql
.rw-rw-r--   565 bohnen 15 12月 17:05  employees.dept_manager-schema.sql
.rw-rw-r--  1.1k bohnen 15 12月 17:05  employees.dept_manager.000000000.sql
.rw-rw-r--   378 bohnen 15 12月 17:05  employees.employees-schema.sql
.rw-rw-r--   18M bohnen 15 12月 17:05  employees.employees.000000000.sql
.rw-rw-r--   410 bohnen 15 12月 17:05  employees.salaries-schema.sql
.rw-rw-r--  119M bohnen 15 12月 17:05  employees.salaries.000000000.sql
.rw-rw-r--   425 bohnen 15 12月 17:05  employees.titles-schema.sql
.rw-rw-r--   22M bohnen 15 12月 17:05  employees.titles.000000000.sql
.rw-rw-r--   138 bohnen 15 12月 17:05  metadata
```

- {database}-schema-create.sql  データベースを作成するDDLが入ったSQL
- {database}-{table}-schema.sql テーブルを作成するDDLが入ったSQL
- {database}-{table}-{\d+}.sql データが入ったSQL

### MySQL/TiDBからs3に分析用にデータをエクスポート

Dumplingでデータをexportして、AthenaやDuckDBから利用することを想定してみます。

S3へのアクセスは環境変数からクレデンシャルを読み取ってくれます。(`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`)
EC2の場合はインスタンスプロファイルを設定するとこれらが自動的に設定されると思いますが、MacOS等から実施する場合はこれらをセットしてください。

:::note
S3環境変数をセットするオプションもありますが、ここでは割愛します。`tiup dumpling --help`で参照できます。
:::

```bash
tiup dumpling -h 127.0.0.1 -P 3306 -u root -p <password> \
-B employees -o s3://<bucket>/ --filetype csv --compress gz \
-m --output-filename-template '{{.DB}}/{{.Table}}/{{.Index}}'
```

#### オプション説明

- -m スキーマファイルを出力しません
- --compress ファイルの圧縮方式を指定します
- --output-filename-template ファイル名のパターンを指定します。{{.DB}}はDB名、{{.Table}}はテーブル名、{{.Index}}は連番に展開され、最後にfiletypeで指定した拡張子がついたファイルになります

今回は、`s3://<bucket>/employees/departments/0000000000.csv.gz` といったファイルが作成されることになります。日付などをパスやファイル名に含めれば、毎日エクスポートするようなときに便利ですね。

#### 利用例

DuckDBから読み出してみます。DuckDBはS3のファイルを直接扱えます。下記の記事で設定方法等書きましたので参考にしてください。

https://qiita.com/bohnen/items/2ab4f13e655605bf168c

```sql
 select * from 's3://<bucket>/employees/departments/*.csv.gz';
┌─────────┬────────────────────┐
│ dept_no │     dept_name      │
│ varchar │      varchar       │
├─────────┼────────────────────┤
│ d001    │ Marketing          │
│ d002    │ Finance            │
│ d003    │ Human Resources    │
│ d004    │ Production         │
│ d005    │ Development        │
│ d006    │ Quality Management │
│ d007    │ Sales              │
│ d008    │ Research           │
│ d009    │ Customer Service   │
│ d010    │ Example Department │
│ d011    │ TiDB Department    │
├─────────┴────────────────────┤
│ 11 rows            2 columns │
└──────────────────────────────┘

```

s3上のファイルをワイルドカードありで直接扱えるのは便利ですね。

### TiDB Cloud Serverlessからデータをエクスポート

:::note warn
TiDB Cloud Serverlessにはexport機能があるので、exportのためにDumplingを使う必要はないです
:::

TiDB Serverlessはtls必須ですので、tls接続のサンプルとしてserverlessからdumplingを行ってみます。

```bash
tiup dumpling -h <SERVERLESS_HOST> -P 4000 -u <SERVERLESS_USER> \
-p <SERVERLESS_PASSWORD> -o output --ca /etc/ssl/cert.pem
```

#### オプション説明

- --ca サーバ証明書ファイルのパス

サーバ証明書を与えるオプションを付けるだけでTLS接続します。上記はまたデータベースの指定をしていないので、すべてのデータベースをエクポートします。

### 最新のテーブル定義を収集

データを出力せずに、テーブル定義だけを定期的に出力して、保存したりgitを更新したりするケースです。

```bash
tiup dumpling -h 127.0.0.1 -P 3306 -u root -p root -d -o output
```

#### オプション説明

- -d データを出力しない

データを取得せず、スキーマファイルのみを出力します。-B を指定していないので、すべてのデータベースが対象になります。

### その他のオプション

その他によく使うオプションとして、下記のものがあります。各オプションの詳細は公式ドキュメントを参照ください。

- -t スレッド数の指定。実行するスレッド数を指定します。後の -r オプションとあわせて使うとパラレル読み出しを行い、大きなエクスポートを高速化できます
- -r 分割の指定。出力するときにこの行数でチャンクに分割します。ソースがTiDBの場合はリージョン（データの塊）単位で分割されるので0より大きい数値であればなんでもOKです
- -F 出力するファイルサイズの上限を決めます。TiDBでよみこむ際には一つのファイルを256MB以内におさめておくことが推奨されているので、その単位で分割するために利用します
- --snapshot TiDBの場合、過去断面のスナップショットを取得します。日時が指定できます

TiDBの場合、でなるべくデータベースに負荷をかけずに出力するとき、`-t 1 --snapshot <日時>` のようにすることで、負荷を抑えつつ一貫性を保って出力することが可能です。

## おわりに

Dumplingのオプションをユースケースを例に紹介しました。DumplingはMySQL/TiDBの両方に対応したエクスポートツールで、出力オプションなども柔軟でバッチエクスポートツールとしても利用できます。ぜひご活用ください。