ファイル名は同じなのに中身が変わった
一言でいうと
他人が渡すファイルのスキーマは、通知なしに変わります。そのため、受け取る側がフィンガープリントを固めておき、何が壊れて何が壊れないかをコードで明文化して、自動で判定する必要があります。
なぜ必要なのか
毎週月曜日に、同じ名前のファイルが届きます。12週間、何の問題もありませんでした。13週目に、ダッシュボードの売上が0になります。ファイルを開いてみると、カラム名の1つがamount_krwからamountに変わっています。送った側は「フィールド名を整理した」と言います。知らせてくれなかった理由は単純です。向こうは、それが私たちのパイプラインを止めることだと知らなかったのです。
この出来事が繰り返される構造的な理由があります。送る側は自分のシステムのスキーマを変えただけで、受け取る側はそれを契約として使っていました。この2つの事実の間に文書がなければ、変更はいつも静かに届きます。しかも、私たちは変える側を管理できません。本番DBなら、旧スキーマと新スキーマを共存させながら移行できますが、他人のファイルには、そうした余地がありません。
そのため、できることは1つだけです。変わったという事実を、パイプラインが先に察知できるようにすることです。
どう動くのか
受け取ったファイルからスキーマを取り出して、フィンガープリントとして固めます。フィンガープリントに入れるのは、カラム名と順序、カラムごとに推論した型、そして値のサンプルです。名前と型だけをつなげてハッシュを出せば、短いフィンガープリントが1つ出てきて、それが先週と違えば、何かが変わっています。
型の推論は、基準を先に決める必要があります。空の値を除いて残った値がすべて整数の形ならint、小数まで含むならfloat、すべてYYYY-MM-DDならdate、それ以外はstrとみなします。これは推論であって宣言ではありません。そのため、どんな基準を使ったかがコードに書かれていてこそ、あとで間違ったときに直す場所がわかります。
そのあと、先週のフィンガープリントと照合して、変わったものを5つに分けます。
| 種類 | 何が見えるか | どう突き止めるか |
|---|---|---|
| 追加 | なかったカラムが増えた | 名前の集合の差 |
| 削除 | あったカラムがなくなった | 名前の集合の差 |
| 名前の変更 | 1つが消えて1つが増えた | 消えたカラムと増えたカラムの値サンプルが大きく重なるか |
| 型の変更 | 同じ名前の型が変わった | 推論した型の比較 |
| 意味の変更 | 何も見えない | スキーマでは検出できない。値の分布でしか見えない |
名前の変更を値で突き止めることが核心です。名前だけを見れば、消えたものと増えたものの2件ですが、値サンプルがほとんど同じなら、同じカラムが名前だけを変えたということです。この判定があれば、パイプラインは「マッピングを1つ追加すれば済みます」と答えられます。
最後の行が、このラボで一番重要です。意味の変更は、スキーマ検査では絶対に検出されません。金額の単位がウォンから千ウォンに変わっても、カラム名も型もそのままです。検査はすべて通過し、売上だけが1000分の1になります。
現場での姿
1つ目に、知らないカラムに驚いて止まります。送る側が自分の必要でカラムを1つ追加することはよくあり、そのために私たちのロードが止まる理由はありません。そのため、ルールの基本は知らないカラムは通すです。逆に、なくなった必須カラムは中断です。この2行が互換性ルールの骨格で、残りは、その間のどこかに置かれます。
2つ目に、必須と任意を区別しません。区別がなければ、すべての削除が同じ重さで扱われ、誰も警告を読まなくなります。必須カラムの一覧は業務が決めるものであって、データが決めるものではありません。
3つ目に、型が広がったものと壊れたものを同じに扱います。intがfloatになったのは、たいてい小数の表記に変わっただけなので、計算はそのままできます。intがstrになったものは、合計が文字列の連結になるか、例外が出ます。2つを同じ等級にしておくと、警告が役に立たなくなります。
4つ目に、分布を見ません。意味の変更を検出する唯一の方法は、値の分布を先週と比べることです。中央値が3倍以上に跳ね上がったか、3分の1未満に落ちたなら、人が見る必要があります。これは証拠ではなく手がかりです。実際にその週に大口の取引が集中したのかもしれません。手がかりを人に渡すところまでが、機械の役割です。
実務で本当に大切なこと
- フィンガープリントをファイルと一緒に保管します。「先週と違う」と言うには、先週がどこかに書かれていなければなりません。
- 互換性ルールを、文書ではなくコードで明文化します。文書にしかなければ誰も読まず、読んでも判定が人によって違います。
- 必須カラムの一覧は、業務から受け取ります。エンジニアが1人で決めると、あとで変える根拠がありません。
- 分布の監視は、手がかりを作ることです。止めずに知らせ、判断は人が行います。
次のラボですること
同じ注文30件を7週間にわたって、スキーマだけを変えながら出力する再現ツールを実行して受信箱を作ったあと、スキーマツールschema.pyを1ステップずつ育てます。フィンガープリントを固め、追加と削除を分類し、値サンプルで名前の変更を突き止め、型の変更を分け、互換性ルールをcontract.jsonとして宣言して、passとwarnとstopを自動で判定します。最後に、名前も型もそのままで単位だけが変わったカラムを値の分布で検出し、スキーマ検査が何を見られないかを数字で示します。