- 記事作成日:2022/12/12
情報
名前 | URL |
---|---|
Github | https://github.com/kauche/splanter |
公式サイト | https://note.com/kauche/n/ne033cde0c9ea |
デモサイト | |
開発母体 | カウシェ |
version | 0.1.0 |
言語 | Go |
価格 | 無料 |
ライセンス | MIT |
何ができるもの?
- YAML で DML を定義することで、冪等性のあるテーブルデータを splanter で用意できる
利用シーン
開発環境での利用を目的として開発していますが、「データを Insert (or Update) する」という性質から、「動的には更新されないマスターデータ」などを更新する用途で本番環境でも利用できます。
登場背景
splanter は「テストや動作確認で利用する開発・ローカル環境向けのデータを YAML で記述してリポジトリにコミットし、開発者間で共有したい」というモチベーションから開発しました。
所感
- yaml で定義できるのは嬉しいし楽
- mutation 制限が入っていない点に注意
- Array にまだ対応していないので、限定的な利用になる
使い方
今回のコード - framinal-new-tools/splanter at main · lirlia/framinal-new-tools
インストール
Release v0.1.0 · kauche/splanter からダウンロード
もしくは go install github.com/kauche/splanter@latest
準備
以下の設定で db を作っておきます。
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
ddls 配下に以下のファイルを配置します。
Singers.yaml
- SingerId: '1' FirstName: 'Marc' LastName: 'Richards' - SingerId: '2' FirstName: 'Catalina' LastName: 'Smith'
Albums.yaml
- SingerId: '1' AlbumId: '1' AlbumTitle: 'Total Junk' - SingerId: '1' AlbumId: '2' AlbumTitle: 'Go, Go, Go' - SingerId: '2' AlbumId: '3' AlbumTitle: 'Green' - SingerId: '2' AlbumId: '4' AlbumTitle: 'Forever Hold Your Peace'
ディレクトリ構成はこれ。
. ├── ddls │ ├── Albums.yaml │ └── Singers.yaml ├── docker-compose.yml ├── schemas │ └── db.sql └── splanter
inset してみる
insert 前
❯ ./splanter --project PJ_NAME --instance riddle --database test-db --directory ./ddls
実行するときちんとデータが入っていました。
複数回実行しても変化がないので、冪等性が保証されているようです。便利!
40,000 mutation を超える場合もいける?
Cloud Spanner のトランザクションあたりの更新回数が 2 倍に増加 | Google Cloud 公式ブログ
Spanner では一回のトランザクションにおいてどの程度の行数、列数、を更新できるのか?が mutation という単位で制限されています。 具体的な計算式はこちら。
Users
テーブルを作って
CREATE TABLE Users ( Id INT64 NOT NULL, ) PRIMARY KEY (Id);
10万件のユーザ追加を試してみます。
- Id: 1 ... - Id: 100000
これを実行してみると、しばらくして mutation 制限に引っかかったので、現在ツールでは対応していないようです。
❯ ./splanter --project PJ_NAME --instance riddle --database test-db --directory ./ddls failed to load data to spanner tables: failed to insert records: spanner: code = "InvalidArgument", desc = "The transaction contains too many mutations. Insert and update operations count with the multiplicity of the number of columns they affect. For example, inserting values into one key column and four non-key columns count as five mutations total for the insert. Delete and delete range operations count as one mutation regardless of the number of columns affected. The total mutation count includes any changes to indexes that the transaction generates. Please reduce the number of writes, or use fewer indexes. (Maximum number: 40000)"
コードを見てもそのまま Apply
しているので、mutation 対応はされていないよう様子。
func (d *DB) Save(ctx context.Context, tables []*model.Table) error { if err := d.sortTablesByDependencies(ctx, tables); err != nil { return fmt.Errorf("failed to sort tables: %w", err) } var mutations []*spanner.Mutation for _, table := range tables { for _, records := range table.Records { mutations = append(mutations, spanner.InsertOrUpdateMap(table.Name, records.Values)) } } if _, err := d.client.Apply(ctx, mutations, spanner.Priority(spannerpb.RequestOptions_PRIORITY_LOW)); err != nil { return fmt.Errorf("failed to insert records: %w", err) } return nil