データエンジニアの自分がジョブを作る時に意識していること

データエンジニアの自分がジョブを作る時に意識していること

データエンジニアの自分がジョブを作る時に非機能ベースで意識することをまとめてみました。AIのルールに使うのもよし、ジョブの確認のときに使うのものよしです。
2025.09.16

はじめに

こんにちは、データ事業本部の渡部です。
今回はデータエンジニアの自分がジョブを作るときに意識していることをまとめてみました。
書く内容としては、機能よりは非機能によった内容となります。

こちらを書こうと思ったきっかけは2つあります。
1つはデータエンジニアの自分がジョブを作る時に意識していることさせかったことからです。
AIが一発で全ての観点において完全な実装をしてくれることはありませんが、一覧化をしておくことでその部分をどうやって実現しているのかをAIに書いてもらったり(もしくは仕様として先に書いたり)、また私がAIに作成してもらったコードをチェックするとき私自身が一覧化されているおかげでチェック観点が明確になる効果がありました。

書こうと思った理由のもう1つは、今回書いた観点で指摘されるジョブがそれなりにあるからです。
私は普段他のエンジニアが作成したジョブを確認することが多いのですが、機能(ジョブで実現したいこと)で指摘することより非機能(ジョブを支えるもの)を指摘することが多いです。
これは機能はエンジニアの心を掴むからです。私もそうです。なお私の言うジョブはETLジョブであることが多いので、データの出力で機能が問題ないかの確認がしやすい側面もあると思います。
対して非機能は機能に比べると注目されないです。機能は明確に設計されますが、非機能は暗黙の了解のような存在になってることもあるでしょう。一度アーキテクチャを決めたら、あまり触れられないというのもあります。
今回の内容はジョブのクオリティを上げるためには必要なことですし、できて当然とされるものなので、指摘されるジョブは勿体ないです。そんなジョブを少しでも救えたら嬉しいです。

大部分の人が「そんなの知ってるよ〜」な内容で初心者向けとは思うのですが、ご参考になれば嬉しいです。
今回は一覧とその内容と意識する理由・書けたらアンチパターンを書いています。また誰でもわかるように書くことをなるべく意識しています。

意識すること一覧

ジョブ作成時に意識していることは以下となります。
順番は関連のあるものを近づけてはいますが、それ以外に他意はありません。

  • トリガー
  • 冪等性
  • 並列実行制御
  • ロールバック
  • リトライ
  • タイムアウト
  • ログ
  • 通知
  • パフォーマンス
  • リソース管理
  • セキュリティ
  • 設定管理

意識することの概要

トリガー

トリガーとは、ジョブが「いつ」実行するのか、そのきっかけを定義することです。主にスケジュール(定時)、イベント(何かが起きた時)、手動(人が操作した時)があたります。

もしもトリガーがなければ、ジョブはただの置物です。
適切なトリガーで実行されなければ、ジョブ単位では優秀であってもジョブ間での順序性がとれずに、古いデータでDWHを書き換えてしまったりしまいます。

アンチパターンとしては、ジョブのトリガーを分岐・連鎖させすぎて一体どこで失敗したかわからなくなるということです。
ジョブのフロー図であったり、データパイプラインならリネージュとともに管理したり、どこかのDBでジョブの状態管理をして不明にならないようにします。

冪等性(べきとうせい)

冪等性とは同じ操作を何度繰り返しても、結果が常に同じになるという性質のことです。ベキトウセイ、初見じゃ読めませんよね。私は初見でカトウセイ・・?と読んでツッコまれました。

ジョブはネットワーク障害やデータの制約違反など、様々なエラーで失敗します。またトリガーについてEventBridgeやEventracに代表されるように、「少なくとも1回起動」を保証とするサービスはよくあります。これは複数起動されるかもしれないよ、ということです。
もしも冪等性が担保されていなければ、エラーが起きた後の再実行や重複実行をされることで、データの二重登録が発生されてしまうかもしれません。
特にDWHではPKを設定していても重複データを入れられてしまうので、ジョブでしっかりと冪等性を担保する必要があります。
接続エラーになったら再実行で問題ないように、データの制約違反ならデータさえ直せば問題ないように、ジョブが複数回起動されても問題ないように冪等性あるジョブを組みます。

具体的な対策としては、Delete + InsertやUpsert(Update + Insert)・洗い替えでデータ連携を組んだり、処理済みフラグを使用したジョブ実行管理テーブルの使用、テーブル定義にバージョンを持たせて最新バージョンのデータのみを参照するビューを作ることがあげられます。

並列実行制御

並列実行制御とは、同じジョブが同時に複数実行されることをOKとするかどうか、OKならどれくらいの回数をOKとするか制御する仕組みのことです。
これを書いてて思い出したのですが、以前「多重度の設定は?」とお客さまに言われてなんのこっちゃわからなくて恥ずかしい思いをしました。多重度も同時に実行するジョブの数という意味合いで使われることがあります。

さて並列実行はそれぞれのワーカーに処理を任せることで、リソースの分割ができて処理時間も早く済ますことができたりするスグレモノです。
そんなスグレモノですが、取り扱い注意です。並列実行がされても問題ないようにジョブを組む必要があります。
よくあるアンチパターンは、同時に実行されるジョブで操作する一時ファイルや一時テーブルを同じものにしてしまって別のジョブで書き換えたデータを別のジョブが読み込んでデータの不整合を起こしてしまったり、APIの同時実行数の上限を超えて並列でジョブを組んでエラーを起こしたり、並列にしすぎてコンピューティングリソースを食い潰して別のリソースに影響を与えてみたり、です。
並列にするのであれば、ジョブの独立性やサービス上限・他リソースへの影響など、広い視野でジョブ設計をします。

特に必要がなければ、並列数を1にしてまとめて処理をするのがよいですね。

ロールバック

ジョブの処理途中でエラーが発生した際に、処理開始前の状態にデータを戻すための戦略や手順のことです。

DBに関わったことがある人ならなんとなくわかると思いますが、ロールバックを担保できなければ誤ったデータを読んだり書き込んでしまうかもしれません。
よくある例としてはATMがあげられますね。ATMで出金したのにお金が出てこず、ただ手帳残高が減らされたなんてことがあったらたまったもんじゃありません。
データエンジニアのよくあるアンチパターンとしては、洗い替え処理でTRUNCATE TABLEがコミットされたあとのINSERTが失敗してテーブルが空っぽになってしまうという事象です。INSERT処理が複雑であれば、リカバリまで長い間データが参照できない状態となってしまいます。
そのため別名で一旦CTASでテーブルを作成して、テーブル削除、テーブル名置き換えというようにする手法がとられます。そもそもDelete + InsertやUpsertという連携方法をとるのもよいです。

ただいつでも完全なロールバックが必要、というとそんなことはありません。
逆に巨大トランザクションを作ったあまり、テーブルを長時間ロックしたり、エラー時の手戻りが大きくなってしまうこともあります。
ジョブは何かしらのサービスのためにあるので、そのサービスレベルを満たせるように現実的な設計をします。
地味ですが、エラー処理を考えるときは一つ一つのジョブを指差しながら、「もしここで処理がエラーになったら?」と考えるのが良いと思います。

リトライ

ネットワークの瞬断など一時的なエラーが発生した場合に、処理を自動的に再試行する仕組みです。
私がエンジニアになりたての頃は完璧な設計(そんなものはない・・・)があれば、ジョブがエラーになることなどないと思っていました。
幻想ですね。ジョブはエラーになります。多様性あるエラーが発生します。
何であってもエラーになるものと考えられるようになった頃がエンジニアとしてのスタートラインだったかもしれません。

とはいえ全てのエラーを人間が手動で再実行させるのは非効率です。
一時的な問題で時間を空けて再実行をすればうまくいくのであれば、それは自動的にリトライ処理を組みましょう。
StepFunctionsはじめワークフローのツールでは機能としてリトライ処理が用意されていることが多いです。

なお前述しましたが、ここでは冪等性が大事になります。
リトライされても想定通りの結果になるのかを考えながら、リトライ処理をいれましょう。

タイムアウト

ジョブが想定以上に長く実行されている場合に、強制的に処理を停止させるための制限時間設定です。

タイムアウトが設定されていないあまり、無限ループやハングアップといった異常事態に陥ったジョブが動き続け、重課金が発生・・・なんてことは結構ある事象です。読者様の中にもドキッとした方はいるのではないでしょうか。

昨今はデフォルトでタイムアウト時間が設定される良心設計なサービスが多いので遭遇しづらいと思いきや、自分でジョブフローを組んだときにフローにタイムアウトが仕掛けられておらず、ぐるぐるぐるぐる無限ループが発生することもあるので要注意です。

ログ

ジョブの実行状況(開始、終了、エラー、主要な処理ステップなど)の記録です。

ログはエラーが発生した際に、何が起きたのかを追跡・分析するための唯一の手がかりです。
そのためログにはどこのステップでエラーになったのか・エラー理由を特定するための情報を盛り込ませる必要があります。
しっかり成功・エラーの時のログをチェックし、ログの機能を果たせるかをテストしましょう。

ただ気をつけるアンチパターンは別にもあります。
それはデータを何も考えずにログに出力させてしまったり、とりあえずログは詳細であればいいという思想からBIGなログを作ってしまうことです。
データの機密性を考えずに、もしもログが誰でも見れるようなところに出力されてしまったり、大きなログを作るのに処理が重くなったり、ちりつもでログの保存料金が大変なことになったりするのは避けたいです。

通知

ジョブの実行結果(成功、失敗、警告など)を、関係者に知らせる仕組みです。

主な用途としてはジョブが失敗したことや、正常に動いていないことに迅速に気づくため設定します。
成功通知に関しては、データマートへの連携が終わったことをデータ活用者に通知するなど、後続の作業があるときに使用します。また別の使い方としては、ジョブが動いていないことに気づくというために通知させることに使用したりします。
ジョブが動いていないことに気づくためにはCloudWatchメトリクスで呼び出しメトリクスを見てのアラームで設定できますが、成功通知というのも一案としてあるのは用途として頭の隅に置いておくといいと思います。

アンチパターンとしては、まず通知先を個人のメールアドレスにしてしまって、その人が退職後通知が届かなくなることがあげられます。SlackやTeamsのチャンネルに通知したり、グループのメーリングリストを使用したり、オペレーションを工夫したい場合はインシデント管理ツールを使うなどの解決策をとりましょう。
また他のアンチパターンとして上述したリトライにも関連するのですが、リトライの回数分通知をさせてしまう通知爆撃も時たまあります。通知爆撃で本来気づかなければならない通知を気付けないことがあるので、注意して設計しましょう。
全て同じ通知をするのも避けるべきです。少なくとも失敗・警告は件名や通知先などで、グラデーションを変えましょう。トイレの電球が切れても、コーヒーをこぼしても、本当の火事でも全館で同じ音量で放送をしていたら、誰も逃げなくなるのと同じです。

パフォーマンス

ジョブの実行効率のことです。

ジョブの実行時間が長すぎると、次のスケジュールに間に合わなかったり、コンピューティングリソースを食ってしまい他のシステムに影響を与えたりします。ジョブの実行時間で料金がかかるサービスであれば、課金増にも繋がってしまいます。
ロールバックのところでも述べましたが、それぞれのジョブは何かしらのサービスのためにあります。そのサービスが保証するサービスレベルを満たせるようにジョブも組む必要があります。例えばサービスレベルが「業務開始の9時までに前日データがデータマートに更新されていること」であるならば、データ連携のジョブはそれまでに完了している必要がありますね。
サービスレベルが実現されているのかがわかるように、別途通知やメトリクスをとって観測できるようにしておきます。当初の想定がずっと続くということはなく、データ量が増えて処理時間が長くなるなど状況は逐一変わるためです。

リソース管理

ジョブが使用するCPU、メモリ、ディスクI/Oなどの計算資源(リソース)を適切に制御・監視することです。

パフォーマンスのところでも書きましたが、一つのジョブがリソースを使いすぎると、同じサーバー上で動いている他のジョブやアプリケーションの動作を妨げ、システム全体が筋肉痛になります。ジムの器具を独り占めしてはいけないですよね。共有リソースを適切に使うマナーが、システム全体の安定稼働につながります。

昨今は自動的なスケーリングがサービスとして用意されていたりして、気にする機会は少なくなりましたが、SaaSをEC2にインストールして使ったりするときなど、使用している技術がどのようにリソースを使い、そのリソースはどのように管理されているのかは把握しておきましょう。

よくあるアンチパターンとしては、それぞれ担当が異なるさまざまな機能・サービスを一つのコンピューティングリソースに盛り込んで、連携不足でリソースがダウンしてしまうことです。
本来は責任を分解できるようにリソースをわけるのがベストですが、現実そうはいかないこともあるかもしれません。もしまとめたいのであれば、リソースを管理する人やシステムを立てて連携がうまくいくように回るようにしましょう。

セキュリティ

ジョブが扱うデータや、ジョブの実行環境を不正なアクセスや攻撃から守るための対策です。

ジョブではセンシティブな情報は扱わないようにしたいですが、そうは言えない場合もあります。
AWSではじめる実践データマネジメント | 技術評論社」で書かれていた言葉を借りるのですが、データ基盤への機密情報は「持ち込ませない」「残さない」「使わせない」の三原則で考えると良いと思います。
そもそもデータ基盤に機密は「持ち込ませない」、持ち込んだとしても人間にはわからないように匿名化・仮名化し「残さない」、どうしても機密情報を使わなければならない場合は認可がない人には「使わせない」ようにします。

アンチパターン、でもないですがアクセスキーを使用した実装はなるべく避けて、一時的な権限借用の仕組みをとるなどをしましょう。アクセスキーなど永続的な権限を持つものが漏洩してしまうと大変な事態ですから、より危険が少ない方法を取るのがベターです。
他に気を付けるポイントとしては、追加開発です。
しっかりプロジェクトで共通のアーキテクチャを組んで軌道に乗ったあと、何かしらの機能の追加だったり変更を入れたくなることはあると思います。例えばエラーをすぐ直すことができるように、エラーデータを通知したいとか、ログを詳細化したいとかですね。
メールにデータをそのまま記載されるようにしたり、誰でも見れるログ置き場にデータが出力されたりする追加機能が作られたらば、しっかりしたアーキテクチャが泣いてしまいます。

設定管理

データベースの接続情報やAPIキーなど、環境によって変わる値をコード本体から分離して管理することです。
ハードコードはいけない、とプログラミングを学び始めた時に言われるアレです。

ハードコードをしないことで、コードを変更せずに設定を簡単に切り替えられるのがいいんですよね。
開発環境と本番環境の設定を簡単に切り替えられるようにするためです。また、機密情報をコードに直接書き込むことを防ぎ、セキュリティを向上させることが可能です。

アンチパターンとしては、設定ファイルをGit連携してしまったり、ログに出てしまうところでパラメータを管理してしまうことなので、気をつけましょう。

さいごに

いかがでしたでしょうか。
思いつく限りで書いていきましたが、こういうのもあるよねということはあるかもしれません。それでも大部分は書き出せたかなと思います。

今回はジョブをつくるときに考えることを書きましたが、そもそもジョブを作る前の技術選定だったりサービスの特徴を知る時にも流用可能です。
ぜひ色々な場面で立ち返って考えていただければと思います。

この記事をシェアする

FacebookHatena blogX

関連記事