qube: Zstandard Seekable Format対応

自作のDB負荷テストツール qube を Zstandard Seekable Format に対応させた。

Zstandard Seekable Format is 何?

github.com

名前の通りシーク可能なZstandardのフォーマット。 ファイル末尾にシークテーブルをつけて解凍しなくても任意のオフセットからデコードしたデータを読み取れる。 シークテーブルは通常のzstdでは単純に無視されるので、zstdコマンドでも解凍可能。

こちらの記事が詳しい。

qiita.com

本家実装済みだが、CLIは提供されていない模様。

GoとRustの実装にはCLIもある。

Goのサンプルコードは以下の通り。

seekable-zstd-sample.go

qubeで何がうれしい?

qubeはクエリログをテストデータとしてDBの負荷テストを行うために開発したツールだが、テストデータは5〜10GBと大きくなりがちで取り回しが非常に悪い。(テストサーバへの転送に時間がかかる、jqでテストデータをフィルタリングしているとディスクが埋まる…etc)

なので圧縮ファイルを使えると便利なのだが、シーク可能である必要があったので、gzipやbz2が使えなかった。

なぜシークが必要かというと、データをメモリ上でシャッフルする代わりにランダムな行からデータの読み込みを行う機能をつけているので、ファイルの任意のオフセットにシークできる必要があった。

あと、ループ終了時の巻き戻しに io.Seeker など os.File と共通のインターフェースを使えた方がうれしい(seekable zstd では io.ReadSeekCloser でtxtファイルとzstファイルを抽象化できたので、だいぶ実装が楽になった)


テストデータをzstdseekで圧縮すると1/10になったが、qubeの使い勝手は変わらない。便利。 (クライアント側のCPU消費は増えると思う)

$ go install github.com/SaveTheRbtz/zstd-seekable-format-go/cmd/zstdseek@latest
$ zstdseek -f data.jsonl -o data.jsonl.zst
$ ls -lh data.jsonl*
-rw-r--r--@ 1 sugawara  staff   235M  7 13 09:28 data.jsonl
-rw-r--r--@ 1 sugawara  staff    23M  7 13 09:36 data.jsonl.zst
$ qube -d 'root@tcp(127.0.0.1:13306)/employees' -f data.jsonl.zst -n 5 -t 10s --random
00:05 | 5 agents / exec 89821 queries, 0 errors (22555 qps)
...
{
  "Options": {
    "DataFiles": [
      "salaries.jsonl.zst"

結構便利なフォーマットなので今後も使う機会がありそう。