はじめに
連載「Genie Codeと学ぶDatabricks」の第4回です。
ここまでの3回は、ノートブックで「読み込んで、変換して、保存する」を手で組んできました。今回はこれをパイプラインにします。使うのはLakeflow Designerというノーコードツールと、その裏側にあるLakeflow Spark Declarative Pipelines (SDP) です。
この2つ、「どちらもETLパイプラインを作るもの」なので機能が被っているように見えます。私も最初はそう思いました。しかし実際に触ると、DesignerとSDPは競合ではなく表と裏の関係だと分かります。今回はその関係を、いつも通り手を動かして確かめます。この回だけ「作らせる」役をGenie CodeではなくDesignerが担い、「読み解く」対象が生成されたパイプラインコードになる、という構成です。
環境はDatabricks Free Editionです。
Lakeflowとは何者か
Lakeflowは、Databricksのデータエンジニアリング機能群の総称です。データの取り込み (Lakeflow Connect)、変換パイプライン (Lakeflow Spark Declarative Pipelines)、オーケストレーション (Lakeflow Jobs) がこの傘の下にあり、Designerはその最前面に付いたノーコードのフロントエンドです。
鍵になるのは「宣言的 (Declarative)」という考え方です。ここまでの回で書いてきたのは手続き的なコードでした。読み込んで、フィルタして、集計して、保存する、という手順を順番に書く。宣言的パイプラインでは逆に、「このテーブルは、このクエリの結果であるべき」という最終状態だけを書きます。ではいつ・どの順番で・どう更新するのかは、依存関係も含めてランタイム側が解決します。
説明だけでは伝わらないので、まず表側から触ります。
表側: Designerでパイプラインを組む
Lakeflow Designerで作る資産は「ビジュアルデータの準備」と呼ばれます (執筆時点ではベータ)。新規作成すると、左に演算子のパレット (ソース、フィルタ、集計、結合、さらにAI関数まで)、中央にキャンバス、下に自然言語の指示欄とプレビューが並んだ画面が開きます。
お題はこの連載でおなじみの「samples.tpch.ordersから1998年の注文に絞って、月別の受注金額を集計する」です。第1回でGenie Codeにノートブックとして作らせた処理を、今度はパイプラインとして組み直します。
ソースとしてsamples.tpch.ordersを指定したら、変換は自然言語で指示します。
1998年の注文だけに絞り、月別の受注金額合計を集計してください
するとキャンバス上に「1998年注文で絞り込み」「月列追加」「1998年月別受注金額合計」という3つの演算子が生成され、フローがつながりました。そして注目したいのが、ここでも即座に反映されるのではなく「変更を拒否 / すべて承認」の承認待ちになることです。Genie Codeがノートブックへの書き込み前に承認を求めてきたのと同じ、AIが提案し、人間が承認するという型が、Designerでも一貫しています。
各演算子を選ぶと、その時点での入力と出力をプレビューで確認できます。出力には受注月ごとの合計受注金額が並び、フローが意図通りに動いていることが分かります。
最後に、出力先としてworkspace.tpch_learningスキーマ配下のテーブルを指定して保存します。ノーコードと言いつつ、やっていることは第1回のノートブックと同じ「読み込み、フィルタ、集計、保存」です。違いは、これが1回きりの実行ではなく、繰り返し実行できるパイプラインとして定義されたことにあります。
ハマりどころ: プレビューの出力から8月が消えている
ここで手を止めてプレビューをよく見てください。私の環境では、出力の受注月が1〜7の7行しかありませんでした。1998年のデータは8月2日まであるはずなのに、8月がいません。
種明かしをすると、プレビューはデフォルトでスキャン行数に制限 (1000行) が付いたサンプル実行です。1998年8月は2日分しかデータがないため、サンプルに引っかからず、集計結果から丸ごと落ちたわけです。第1回でグラフの末尾を急落させた「部分月」が、今度はプレビューから消える側に回った格好です。
対処はプレビュー右下にあります。「スキャンする行数」を制限から「最大」に切り替えると全量スキャンで再計算され、受注月8が姿を現しました。合計受注金額は約9.4億と、他の月の約146億に対して桁違いに小さい。2日分しかないのだから当然で、これ自体が部分月の証拠です。
まとめると、デフォルトのプレビューは形と型の確認用で、件数の少ないグループはサンプルから落ちることがある。網羅性まで見たいときはスキャンする行数を最大に切り替える。プレビューが7行だからといって慌てて演算子を直し始める前に、まずスキャン設定を確認してください。ここを知らないと確実にハマります。
裏側: 生成されたコードを読む
ここからが本題です。Designerで組んだフローは、見た目の裏で本番運用に耐えるコードとして表現されています。ドキュメントの言葉を借りれば「プロトタイプから本番への移行にリバースエンジニアリングも作り直しも不要」。つまり、ビジュアルなフローとコードが同じものの2つの表現になっています。
その「裏側の言語」がSDPです。どんなコードなのかを読むために、同じ処理をGenie Codeに宣言的パイプラインとして書かせてみます。
ここで1つ注意があります。宣言的パイプラインの構文は、ノートブックでは実行できません。パイプラインのランタイム上でだけ動く構文なので、依頼する場所もノートブックではなくパイプラインエディタです。新規作成からETLパイプラインを作成してエディタを開き、そこのGenie Codeにこう依頼します。
このパイプラインに、samples.tpch.ordersから月別受注金額を集計する処理を
実装してください。
- 1998年の注文に絞る中間ビューと、月別受注金額合計のマテリアライズド
ビューの2段構成にする
- SQLで定義し、各定義の前に宣言的パイプラインの考え方をコメントで説明する
- ターゲットはworkspace.tpch_learningスキーマ
依頼を受けたGenie Codeの動きが、また見事でした。まずパイプライン設定を確認し、ターゲットスキーマがdefaultになっていたのをworkspace.tpch_learningに自分で更新。SQLファイルを作成して実装し、いきなり本実行はせずにドライランで定義を検証してから、「実際にパイプラインを実行してデータセットを作成します」と進めていきます。さらに、パイプライン作成時に付いてくるテンプレートの空ファイル (my_transformation.py) を削除すべきか検討し、「ユーザーに確認してから進める方が良い」と踏みとどまる場面までありました。設定の確認、検証、破壊的操作の留保。ここまでの回で見てきた慎重さのパターンが、パイプラインエディタでも一貫しています。
生成されたコードの全体がこちらです (コメントも含めてほぼ生成のままです)。
-- 中間ビュー: 1998年の注文データ
-- 【宣言的パイプラインの考え方】
-- Temporary Viewは、パイプライン内部でのみ使用される一時的なビューです。
-- Unity Catalogには公開されず、下流のデータセット定義からのみ参照可能です。
CREATE TEMPORARY VIEW orders_1998 AS
SELECT
o_orderkey, o_custkey, o_orderstatus, o_totalprice, o_orderdate,
o_orderpriority, o_clerk, o_shippriority, o_comment
FROM samples.tpch.orders
WHERE YEAR(o_orderdate) = 1998;
-- マテリアライズドビュー: 月別受注金額合計
-- 【宣言的パイプラインの考え方】
-- Materialized Viewは、バッチ処理でソースデータから結果を計算し、
-- Unity Catalog (workspace.tpch_learning) に永続化されるデータセットです。
-- パイプライン実行時に全データが再計算され、常に最新の集計結果が保証されます。
CREATE OR REFRESH MATERIALIZED VIEW monthly_order_totals AS
SELECT
DATE_TRUNC('month', o_orderdate) AS order_month,
COUNT(DISTINCT o_orderkey) AS order_count,
SUM(o_totalprice) AS total_amount,
AVG(o_totalprice) AS avg_order_amount,
MIN(o_orderdate) AS first_order_date,
MAX(o_orderdate) AS last_order_date
FROM orders_1998
GROUP BY DATE_TRUNC('month', o_orderdate)
ORDER BY order_month;
第1回のノートブックのコードと見比べてください。あちらには「読み込む、集計する、保存する」という動詞が並んでいました。こちらにあるのは「orders_1998とはこのSELECTであり、monthly_order_totalsとはこのSELECTである」という定義だけです。手順を書くのをやめて、あるべき状態を書く。これが宣言的の意味です。更新のタイミング、依存する上流の解決、失敗時のリカバリは、パイプラインのランタイムが引き受けます。頼んでいないのに件数・平均・期間の列まで足してくる過剰サービスぶりは、もはやこの連載ではおなじみです。
読み解きのポイントは2段構成の役割分担です。中間ビューはTEMPORARY VIEW、つまりパイプライン内部だけの名前空間で、Unity Catalogには公開されません。だから第2回で作った実テーブルorders_1998と同名でも衝突しない (それでも紛らわしいので、実務なら別名にするところですが)。一方のマテリアライズドビューはUnity Catalogに永続化され、外部から参照できる。パイプラインの中と外の境界が、構文の選択にそのまま現れています。
パイプラインを実行すると、定義から依存関係のグラフが自動で組み立てられます。ビューorders_1998からマテリアライズドビューmonthly_order_totalsへ矢印が伸び、出力レコードは8。Designerのプレビューで一度消えた8月も、本実行ではきちんといます。
DesignerとSDPは「被っている」のか
冒頭の問いに戻ります。機能が被っているように見えた2つの関係は、こう整理できます。
Designerは、SDPというコードをビジュアルに組み立てるための道具です。これは私の解釈ではなく公式の明言で、Lakeflow Designerの発表ブログには「Designerで構築されたすべてのパイプラインは、内部的にLakeflow Declarative Pipelineを作成します」とあり、英語原文ではさらに踏み込んで "Lakeflow Designer pipelines are deployed as Lakeflow Declarative Pipelines–full stop." (Designerのパイプラインは宣言的パイプラインとしてデプロイされる。以上。) とまで書かれています。データエンジニアは、Designerで作られたパイプラインを他のパイプラインと同じように検査・編集できる、とも。
だから「Designerで始めてコードで仕上げる」「コードで書いたものをチームの非エンジニアにはビジュアルで見せる」という行き来ができます。ExcelとCSVが競合しないのと同じで、同じ実体に対するインターフェースが2つある、が正しい理解です。なお表記について補足すると、ブログでは「Lakeflow Declarative Pipelines」、ドキュメントでは「Lakeflow Spark Declarative Pipelines」と揺れがありますが、同じものを指しています。
学習の順序としては、この連載の型がそのまま使えます。まずDesignerか自然言語で動くパイプラインを作り、裏のSDPコードを読み、宣言的の考え方を掴んだら直接SDPを書く。コードが書けない段階でも本番品質のパイプラインが組め、書けるようになったら同じ資産をそのまま深掘りできます。
ハマりどころ
- Free Editionではアクティブにできるパイプラインが種類ごとに1つという制限があります (制限事項)。パイプラインを作り直すときは、古いものを止めてから。「動かない」と思ったらまずこの制限を疑ってください
- 何でもパイプラインにすればよいわけではありません。1回きりの調査や探索はこれまで通りノートブックが向いています。繰り返し実行して鮮度を保ちたいテーブルができたときが、パイプラインの出番です
- DesignerもフルページGenie Codeと同じくベータです。UIの画面構成や導線は今後変わる可能性があるので、この記事のスクリーンショットと多少違っても、ソース → 変換 → ターゲットという流れ自体は変わらないはずです
- 自然言語で組む場合も、第1回の原則は同じです。曖昧に頼めばそれらしいものは出てきますが、集計ロジックの確認は人間の仕事です。そして前述の通り、デフォルトのプレビューはサンプル実行なので、件数を見るときはスキャンする行数の設定を確認してください
まとめ
DesignerとSDPを行き来して分かったことをまとめます。
- Lakeflow Designerはノーコードの表側、SDPはコードの裏側。競合ではなく、同じパイプラインの2つの表現
- 宣言的パイプラインは手順ではなく「あるべき状態」を書く。CREATE OR REFRESH MATERIALIZED VIEWの定義がすべてで、更新・依存解決・リカバリはランタイムの仕事
- ここまでの3回でやった「読み込み、変換、保存」の知識は、そのままパイプラインの読み解きに使える。AIの提案を人間が承認する型もGenie Codeと共通
- Designerのプレビューはデフォルトで制限付きサンプル実行。2日分しかない1998年8月が出力から消えた。 網羅性を見るときは「スキャンする行数」を最大に切り替える
- Free Editionはアクティブなパイプラインが種類ごとに1つ。 作り直す前に止める
- ノートブックとパイプラインの使い分け: 探索はノートブック、繰り返し実行して鮮度を保つものはパイプライン
一番の収穫は、「ノーコードツール」への見方が変わったことでした。コードの代わりに使う妥協の道具ではなく、コードと同じ実体を別の角度から触るインターフェース。裏のコードを読める状態でノーコードを使うと、プレビューで何を確認すべきかが分かり、結果的にノーコードの使い方もうまくなります。
次回はAI/BIダッシュボードとGenie編です。今回作った月別集計のテーブルを、SQLを書かない人に届ける方法を扱います。第2回でカタログエクスプローラーに並んでいた自然言語の質問候補の正体も、ここで回収します。
参考リンク
- Lakeflow Designerの発表ブログ (日本語)
- Lakeflow Designer (日本語ドキュメント)
- Lakeflow Spark Declarative Pipelines (日本語ドキュメント)
- Free Editionの制限事項 (日本語ドキュメント)
- 第1回: 入門編
- 第2回: Unity Catalog編
- 第3回: Delta Lake編



