Databricks Certified Data Engineer Associate 教科書
第4章 Lakeflow Jobsによるオーケストレーション(Working with Lakeflow Jobs, 16%)
🎯 この節の学習目標
4-1 で学んだ DAG は「タスクを決まった順序で流す」仕組みでした。しかし実運用のパイプラインでは、「一時的なエラーならもう一度試したい」「データの有無で処理を切り替えたい」「同じ処理を複数の対象に繰り返したい」といった要求が必ず出てきます。Lakeflow Jobs はこれらをリトライ・条件分岐(If/else、Run if)・ループ(For each)という制御フロー機能で解決します。ノートブックの中に if 文や for 文を書き込むのではなく、ジョブの構造として制御を表現することで、実行状況の可視化・部分的な再実行・並列化が容易になります。
タスクにはタスクレベルのリトライを設定できます。ネットワークの瞬断、外部APIの一時的な過負荷、クラウドストレージの一時エラーなど、「時間をおいて再実行すれば成功する」タイプの失敗(一過性障害)に有効です。
| 設定項目 | 内容 |
|---|---|
| 最大リトライ回数 | 失敗時に何回まで再試行するか(無制限も指定可能) |
| リトライ間隔 | 再試行までの待ち時間。外部システムの回復を待つ余裕を持たせる |
| タイムアウト | タスクの最大実行時間。ハングした処理を打ち切る保険として併用する |
| 通知 | 失敗・成功・開始などのイベントをメールや連携先(Slack、Webhook 等)に通知する。ジョブ単位・タスク単位で設定可能 |
📝 試験のポイント
「外部システムが時々一時的なエラーを返し、そのたびにジョブ全体が失敗して担当者が手動再実行している。運用負荷を下げるには?」→ 正解の軸は「該当タスクにリトライ(回数と間隔)を設定する」です。「ジョブ全体を二重にスケジュールする」「失敗を無視する」といった選択肢は誤答です。また、リトライはコードのバグによる恒常的な失敗は解決しない点も押さえましょう。何回再実行しても同じバグでは失敗します。
Lakeflow Jobs の条件分岐には、性格の異なる2つの仕組みがあります。「値」で分岐するのが If/else condition タスク、「依存タスクの成否」で実行可否を決めるのが Run if 条件です。
If/else condition タスクは、それ自体が1つのタスクタイプで、指定した条件式の真偽を評価します。条件には、ジョブパラメータや、前段タスクがセットした task values(4-1)を使えます。条件式の結果に応じて、後続タスクを「true 側の枝」と「false 側の枝」に振り分けます。
💡 具体例:新着データの有無で処理を切り替える
前段の取り込みタスクが、処理した件数を task value(例:new_records)にセットします。続く If/else condition タスクで「new_records > 0」を評価し、true なら変換タスクへ、false なら変換をスキップして「新着なし」の記録タスクへ進めます。データがない日に重い変換処理を空回りさせない、という無駄の排除がノートブックのコードではなくジョブの構造として表現でき、実行履歴の画面でもどちらの枝に進んだかが一目でわかります。
Run if は独立したタスクタイプではなく、各タスクが持つ実行条件の設定です。既定では「依存先タスクがすべて成功したら実行(All succeeded)」ですが、これを変更できます。主な条件は次のとおりです。
| Run if 条件 | 実行されるタイミング | 典型的な用途 |
|---|---|---|
| All succeeded(既定) | 依存先がすべて成功したとき | 通常の後続処理 |
| At least one succeeded | 依存先の少なくとも1つが成功したとき | 複数ソースのうち一部でも取り込めたら集計を進める |
| None failed | 失敗した依存先がないとき(スキップは許容) | スキップされた枝があっても続行したい処理 |
| All done | 成否を問わず依存先がすべて終了したとき | 一時リソースの後片付け、実行結果の記録 |
| At least one failed | 依存先の少なくとも1つが失敗したとき | 失敗時の後始末や詳細なエラーレポート作成 |
| All failed | 依存先がすべて失敗したとき | 全滅時のみ発動させる代替処理 |
📝 試験のポイント
両者の使い分けは「何を条件にするか」で判断します。データの値・パラメータ・task value で分岐したいなら If/else condition タスク、前段タスクの成功/失敗という実行結果で動かしたいなら Run if です。たとえば「上流タスクが失敗したときだけクリーンアップ処理を動かしたい」は Run if(At least one failed)、「取り込み件数が0なら後続をスキップしたい」は If/else condition が正解の軸になります。
For each タスクは、入力値のリスト(配列)に対して、ネストしたタスクを繰り返し実行する仕組みです。入力にはジョブパラメータや task value の配列(例:["tenant_a", "tenant_b", "tenant_c"])を指定でき、各要素の値が繰り返しごとのパラメータとして渡されます。
💡 具体例:複数テナントの日次集計
あるSaaS企業のデータチームが、30テナント分の利用ログを同じロジックで日次集計するとします。テナントごとに30個のタスクを手作業で複製するのは保守が困難です。代わりに、テナントIDの配列を入力とする For each タスクの中に集計ノートブックタスクを1つ置き、並列度を例えば5に設定します。テナントが増えても入力配列に追加するだけで済み、特定テナントの失敗時はその繰り返しだけを再実行できます。
3つの制御フローは「困りごとの種類」に対応しています。試験でもシナリオから適切な制御を選ばせる形式が想定されるため、対応関係を整理しておきましょう。
| 要件・状況 | 使う制御 | 理由 |
|---|---|---|
| 外部APIやストレージがときどき一時的に失敗する | リトライ(回数・間隔) | 時間をおけば成功する一過性障害には再試行が最も単純で効果的 |
| データの有無や値に応じて処理を切り替えたい | If/else condition タスク | task value やパラメータの条件式で true/false の枝に分岐できる |
| 前段の失敗時だけ後始末・通知処理を動かしたい | Run if(At least one failed 等) | 依存タスクの成否そのものを実行条件にできる |
| 複数テナント・複数地域に同じ処理を繰り返したい | For each タスク(+並列度) | 配列の各要素をパラメータに同型処理を並列実行できる |
✅ この節のまとめ
問1. 夜間ジョブの取り込みタスクが、外部ストレージの一時的なエラーで月に数回失敗し、担当者が翌朝手動で再実行している。運用負荷を減らす最も適切な対策はどれか。
正解:A
一時的なエラーはリトライで自動回復させるのが定石で、それでも失敗する場合に備えて通知を設定します。Bは成功時に同じ処理が二重実行される危険があり、根本対策になりません。Cはエラーの隠蔽であり、データ欠損に気づけなくなります。Dは自動化を放棄しており、運用負荷はむしろ増えます。
問2. 前段の取り込みタスクが task value に新着件数をセットする。「新着が1件以上なら変換タスクを実行し、0件なら変換をスキップする」を実現する最も適切な方法はどれか。
正解:B
「値(件数)にもとづく分岐」は If/else condition タスクの役割で、条件には前段がセットした task value を使えます。Aの Run if は依存タスクの成否を条件にする仕組みで、件数のような値では判定できません。Cのリトライは失敗時の再試行であり分岐ではありません。Dのループは繰り返し実行の仕組みで、条件による切り替えには使えません。
問3. 並列に実行される3つの取り込みタスクのうち、どれか1つでも失敗した場合にのみ、エラー詳細をまとめて管理チームに報告するタスクを実行したい。最も適切な設定はどれか。
正解:C
「依存タスクの失敗を条件に実行する」は Run if の典型ユースケースで、「At least one failed」が要件どおりです。Aの既定(All succeeded)では全タスク成功時にしか実行されず、目的と正反対です。Bは成否ではなく値で分岐する仕組みのうえ、常に true では「失敗時のみ」を表現できません。Dの無制限リトライは恒常的な失敗で終わらないジョブを生み、報告の要件も満たしません。
問4. 40個の地域コードそれぞれに対して同一の集計ノートブックを実行したい。地域は今後も増える予定で、処理時間の短縮のため同時に数地域ずつ処理したい。最も適切な構成はどれか。
正解:B
「同じ処理をパラメータ違いで繰り返す+並列度の制御」は For each タスクの設計目的そのものです。地域が増えても入力配列への追加だけで対応でき、失敗した地域のみの再実行もできます。Aは保守困難なうえ直列では時間もかかります。Cの If/else は分岐の仕組みであり繰り返しには不適です。Dはジョブが乱立して管理が破綻しやすく、依存関係や一括の成否管理もできません。