🚀

会計システムの「事実」を護れ!DataformとBigQueryで実現する「イミュータブル」な分析基盤

に公開

どーも、AIの方のy.s.です! エンジニアやってると、いろんなデータ扱うけど、その中でも「会計データ」って、マジで特別扱いしなきゃヤバいやつ、って知ってた? 「売上データが1円ズレてたわw テヘ☆」が許されない世界。それが会計。

なぜなら、会計データ、特に「仕訳」とかって、「一度起きたビジネスの"事実"(Fact)」そのものだから。

今日は、この ⭐︎⭐︎⭐︎censored⭐︎⭐︎⭐︎ 大事な「事実」を、どうやってイケてる分析基盤(Datalake/Datamart)に落とし込むか。なんでBigQueryとDataformの組み合わせが、その最適解なのかをガチで語ってく!

背景

すみません、うちのAI(gemini)が調子乗りました。改めまして、DevOpsグループCREチームのAIじゃない方のy.s.です。

現在弊社では爆速で新規事業が立ち上がっており、それぞれに会計システムの対応が必要になっております。工期は短く、戦力は少ない。さて、どうするか。

🧠Thinking Time!!

ここがつらいよ! 弊社の会計システム

既存の会計システムに乗せようとすると、巨大SQLをなんとかこねこねし、かつ、リグレッション観点で元々のデータ整合性を確認する工数は甚大である。会計DBが本体DBとインスタンスを同じくしているあたり、負荷が大きくて頭の抱えどころ。加えて、既存の考え方だと都度RDSからBigqueryの通信がかかりコストも無視できない。

また、既存の会計システムの考え方だと場合によって明細と科目合計の関連が切れていて、何か数値差異が起こった時に原因を追いにくいという、いつもは気にならないが忙しい時に限って調査が難航するという問題がある。これは科目の振替が原因なのだが、それはロジックのどこか奥底に眠っている……。

もうさ、ワークフローにしちゃおうよー。どのツールでどうやって見たいか、どうレイアウトするかなんて明細が追跡出来るようにさえなっていれば後からどうとでもなるよー(当然経理Tと最低限いつまでに、これが欲しいという事前に擦り合わせております)。"Fast alone, far together"(早く行きたければ一人で、遠くまで行きたければ皆で)とも言いますし、なろうじゃないの、ファーストペンギン。

基本方針

採用技術: Bigquery上で完結するワークフロー、Dataformを利用する

  • プロダクトのデータから事実だけを引っ張ってくる。原則加工しない
    • それぞれの取引を会計イベントとして整形(Transform)する
    • 仕訳を作成する
    • 必要なレポートを集計する
  • BigqueryからBigqueryへincrementalに転送する(後述)ので低コスト
  • Transform層が会計的なビジネスロジックになるが、ここに複雑性を局所化出来る
  • 犠牲的アーキテクチャ: SQL群なので別の言語を使いたくなってもConvertが容易

整形(Transform)方針: TM理論、イミュータブルデータモデルを参考にする

  • 上述理論は基本的にCRUDのうちCreateとReadのみを行う
  • なぜ会計に適応すべきか? 支払いの事実は消えるべきではない。それはキャンセルされるか返金されるのだ
  • 下記のようなデータ構造には監査的な問題がある。加えて、ロジックが複雑になってつらいハズ
    • トランザクションのstatusをこねこねした結果、いつどんなstatusになったのか追えなくなる
    • deleted_flag / display_flag / expired_flagの掛け算……結局それは業務上どんなstateなの? どんなビジネス的な意味を持つの?
  • プロダクトDBの認知負荷の問題は追って解決するとして、PoCとして会計DBでこの考え方を適用する

つまり?

  • Bigquery上で決済情報をウォーって持ってくる(注: 原則加工しないが、ユーザー情報などはガバナンスの観点から削除)
  • イミュータブルデータモデルに変換(大まかなイメージは下記ER図参照)
  • それが出来たら仕訳や仕訳の集計をこねこねする。計算途中の中間テーブルを持てばそのあとはどう加工してもいいわけである

ヨシ! ではhowの部分がどれほどイケてるか、AIの方のy.s.にdelegateして解説してもらいましょう。

🛠️ アーキテクチャ: BigqueryとDataformで作る「DL/DM」

具体的に、こんな感じのレイヤー(層)構造で考えるのがデフォ。

  1. datalake 層: 事実の保管庫
  • 役割: 「生データ」を、そのまま置く場所。
  • ルール: 絶対に加工しない。 ここは「イミュータブル(不変)」な領域。昨日のデータも1年前のデータも、発生した「事実」のまま保存する。
  1. datamart 層: 分析用の"解釈"
  • 役割: datalakeにある「事実」を組み合わせて、分析者や経営陣が見やすい形(例:月次PL、BS、キャッシュフロー計算書、予実管理表)に加工したテーブルを置く場所。
  • ルール: ここのデータは、ぶっちゃけ「導出(Derived)」されたもの。もし間違ってても、datalakeっていう「事実」が残ってるから、いつでも再計算できる。 この安心感がパない。

🤖 Dataformで「信頼できる加工」を実装するキモ

じゃあ、datalakeからdatamartを作る「T」の部分、Dataformでどう書くのよ?って話。
Dataformは、ただSQLを書くだけじゃなくて、「パイプラインの信頼性」をコードで担保できるのがマジで神。

1. ref()関数: 依存関係の自動化

Dataformでは、definitions/フォルダにhogehoge.sqlxみたいなファイルを作って、加工ロジックを書いていく。
datamart層のSQLXファイルで、datalake層のテーブルを参照するとき、テーブル名を直書きしちゃダメ。

-- ダサい例 ❌
SELECT * FROM `my-project.datalake.shiwake`

-- イケてる例 (configブロック) ⭕️
config { type: "table" }
SELECT * FROM ${ref("shiwake_datalake")}

ref("テーブル定義ファイル名")って書くだけで、Dataformが「あ、このマート作る前に、shiwake_datalakeテーブルを先に作らなきゃダメだね!」って、依存関係を勝手に理解して、正しい順番で実行してくれる。マジで賢い。

2. type: "incremental": 追記型データ(事実)と最強タッグ

会計の「仕訳(イベント)」データって、毎日どんどん「追記(Insert)」されていくっしょ?
昨日までのデータはもう「事実」として確定してるのに、毎回ぜんぶ再計算すんの、ダルいしカネかかる。

そんなとき、incremental が最強。

config {
  type: "incremental",
  uniqueKey: ["shiwake_id"]
}

SELECT
  shiwake_id,
  kari_kingaku,
  kashi_kingaku,
  timestamp
FROM
  ${ref("shiwake_datalake")}

${when(incremental(), `WHERE timestamp > (SELECT MAX(timestamp) FROM ${self()})`)}

when(incremental(), ...) っていう魔法の呪文で、「もし差分更新モードなら、このSQL(=前回実行した時間以降のデータだけ取ってこい)を追加で実行して!」ってできる。
これで、新しい「事実」だけを効率よくdatamartに反映できるワケ。

🧠 まとめ: それは「哲学」の実践

DataformとBigqueryで会計分析基盤を作るっていうのは、単なるイケてる技術の導入じゃない。
それは、

  • ビジネスの「事実(Fact)」と、そこから生まれる「解釈(Derived)」を、レイヤーとして完全に分離する。
  • そして、「事実」の不変性を守りつつ、「解釈」の信頼性を担保する。

っていう、超大事なデータマネジメントの "哲学"の実践 そのもの。

datalakeに「事実」がある限り、ウチらは何度だってdatamartっていう「解釈」を作り直せる。
この無敵感が、変化の激しいビジネスをデータで支える基盤になるんよ。

アンタも、ただパイプラインを作るだけじゃなくて、「これは事実か?解釈か?」って問いながら、最強の分析基盤、作ってみて!


そんじゃ、またね! AIの方のy.s.でした!👋

結び

この施策により下記のような嬉しいことがありました。

  • イミュータブルデータモデルの採用により、監査性が上がると共にロジックが極めて簡素化された。もう状態に怯えることはない
  • プロダクトDBと完全に分離しているので会計都合で負荷がかかることがゼロになった
  • SQLは最長80行。規模として1/10以下
  • Bigqueryから直接csv/スプレッドシートを出力出来るので会計SaaSへの連携が楽
  • 別事業でも同様の考え方を使い回せる。scrap & buildが大変楽

一方、下記のような課題も見えてきました。それは、 おいおいね

  • assertionを効果的に使いたい。現在はリコンサイルで会計数値の担保を行っている
  • 権限精緻化: ユーザー情報はLOAD時に削除しているとして、もっと精緻化したい
  • metadataの作り込み。この方の発信全部読む
  • データエンジニア的な考え方を組織に浸透させる必要がある……かも

そんじゃ、またね! AIじゃない方のy.s.でした!👋

最後に

ココナラでは積極的にエンジニアを採用しています。

採用情報はこちら。
https://coconala.co.jp/recruit/engineer/

カジュアル面談希望の方はこちら。
https://open.talentio.com/r/1/c/coconala/pages/70417

See Also

Discussion