カウシェ採用情報
株式会社カウシェの採用情報ページです。 私たちと一緒に世界一楽しいショッピング体験をつくりませんか?
https://enjoy-working.kauche.com/
こんにちは、株式会社カウシェの Architect の伊藤です。
本稿では、カウシェ発の OSS である Google Cloud Spanner 用のデータ投入 CLI ツール「splanter」について、「開発した背景」や「Cloud Spanner の Information Schema を活用した実装方法」を交えて解説します。
splanter は「YAML に記述したデータを Cloud Spanner のデータベースに Insert (or Update) する CLI ツール」です。splanter は「テストや動作確認で利用する開発・ローカル環境向けのデータを YAML で記述してリポジトリにコミットし、開発者間で共有したい」というモチベーションから開発しました。開発環境での利用を目的として開発していますが、「データを Insert (or Update) する」という性質から、「動的には更新されないマスターデータ」などを更新する用途で本番環境でも利用できます。
下記のデータベーススキーマ を例として splanter の使用方法を解説します:
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;
まずは投入したいデータを YAML で記述します。YAML ファイルは <テーブル名>.yaml というファイル名でテーブル毎に作成します。例えば上記のスキーマに対して、下記のようなファイルを作成します:
- SingerId: '1'
FirstName: 'Marc'
LastName: 'Richards'
- SingerId: '2'
FirstName: 'Catalina'
LastName: 'Smith'
- 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'
YAML の各キーはテーブルのカラム名に対応させます。
これらの YAML ファイルを下記のように 1 つのディレクトリに格納します。
$ tree .
.
└── data
├── Albums.yaml
└── Singers.yaml
1 directory, 2 files
上記の YAML で記述したデータを、下記のように splanter を利用して Cloud Spanner 上のデータベースに投入できます:
$ splanter \\
--project <Google Cloud の Project 名> \
--instance <Cloud Spanner の Instance 名> \
--database <Cloud Spanner の Database 名> \
--directory ./data
上記のコマンドを実行することによって、 splanter は ./data ディレクトリに保存した YAML を全て読み込み、データベースにデータを投入します。
また、下記のように splanter の実行時に、 SPANNER_EMULATOR_HOST 環境変数に Cloud Spanner Emulator のホストを指定することで、実際の Cloud Spanner 上のデータベースではなく Emulator 上のデータベースにデータを投入することも可能です:
$ SPANNER_EMULATOR_HOST=localhost:9010 splanter \
--project <Google Cloud の Project 名> \
--instance <Cloud Spanner の Instance 名> \
--database <Cloud Spanner の Database 名> \
--directory ./data
ユニットテストなどで Emulator を利用するときは、この Emulator にデータを投入する機能を重宝しています。
splanter はデータの書き込みを Insert or Update で行っているため、同じ YAML に対して splanter を複数回実行してもエラーは発生せず、単にデータが更新されます。このため、投入したいデータに変更があった場合でもデータベースをリセットする必要はなく、気軽にデータベース上のデータを更新できます。
splanter は Go を利用して開発しています。splanter は大別して「YAML に記述されたデータを読み込む部分」と「Cloud Spanner にデータを投入する部分」から構成されています。
YAML を読み込む部分では、 path/filepath 標準パッケージの WalkDir 関数を利用して YAML ファイルを探索し、 goccy/go-yaml パッケージを利用して YAML に記述されたデータを読み込んでいます。
Cloud Spanner にデータを投入する部分では、Information Schema を活用しています。以下で Information Schema の活用について解説します。
Cloud Spanner は INTERLEAVE を利用してテーブル間に親子関係を持たせることができます。例えば、例として利用しているスキーマでは Albums テーブルが Singers テーブルに INTERLEAVE されているので、 Singers が親テーブル、 Albums が子テーブルとして扱われます。子テーブルのレコードは親テーブルのレコードに紐づくので、対応する親テーブルのレコードが存在しない状態では子テーブルのレコードは作成できません。そのため、splanter はスキーマを解析してテーブル間の親子関係を認識し、親テーブルから先にレコードが作成されるように投入するデータを並び替える必要があります。これを行うために splanter は Information Schema を利用しています。
Information Schema は Cloud Spanner がビルトインで提供する、データベーススキーマのメタデータを提供するスキーマです。Information Schema はスキーマのメタデータをテーブルとして格納しており、このテーブルに対してクエリを発行することでスキーマの構造を把握できます。例えば、splanter では下記のようなクエリを発行してテーブル間の親子関係を解析しています:
> SELECT TABLE_NAME, PARENT_TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ("Singers", "Albums");
+------------+-------------------+
| TABLE_NAME | PARENT_TABLE_NAME |
+------------+-------------------+
| Singers | NULL |
| Albums | Singers |
+------------+-------------------+
この例では、テーブルのメタデータを格納している Information Schema の TABLES テーブルにクエリを発行し、テーブル間の親子関係を取得しています。splanter はこの情報を元に、親テーブルへのデータが先に投入されるようにデータを並び替えています。
Information Schema は TABLES テーブルの他にも、テーブルのカラムの情報を格納する COLUMNS テーブルや、テーブルの制約の情報を格納する TABLE_CONSTRAINTS テーブルなどを持っており、スキーマを解析するのに重宝します。Information Schema は、例えば上記のクエリの発行するのに利用した、Cloud Spanner に CLI からインタラクティブにクエリを発行するためのツールである spanner-cli や Cloud Spanner のデータベーススキーマを管理するためのツールである wrench などの OSS でも利用されています(余談ですが、筆者はオーナーとして wrench を開発したり、 spanner-cli に機能追加でコントリビュートしたりしています 😎)。
本稿では、カウシェ発の OSS である splanter について、開発した背景や Information Schema を活用した実装方法を交えて解説しました。
splanter を利用することで、データの投入が楽に行えるようになり開発の生産性が向上するので、Cloud Spanner を利用している方はぜひお使いいただければと思います。また、Information Schema を活用することで、スキーマの構造を柔軟に解析することができるので、これを利用してぜひ新しいツールを開発していただければと思います。
弊社カウシェでは「Try First」というバリューを掲げており、本稿で解説した splanter のように新しくツールを実装して OSS として公開する、というようなことにも積極的に Try していく文化を作っています。エンジニアにとっては非常にエキサイティングな環境なので、もし弊社に興味を持っていただいた場合は、ぜひ採用情報をご覧いただければと思います。
採用情報
また、Meety でカジュアル面談を募集しているので、こちらもぜひご応募ください(「カウシェへの転職に興味はないけど技術の話をしたい!」という方も歓迎しています!)。