Fundamentals of Data Engineering 第7章

結構頑張って進んできたな

Data Ingestionとは

Data Ingestion(取り込み)は、データをソースシステムから別のストレージ/システムへ移すこと。

つまり基本的には、

ソースシステム ↓ データ取り込み(ingestion) ↓ ストレージ / 最終地点

という A地点からB地点へのData Movement を指します。

  • データ取り込みとデータ統合(integration)は違う

データ取り込み → データを移動する

データ統合 → 複数ソースのデータを組み合わせて、新しいデータセットを作る

例えば、

CRM 広告Data Web Analytics ↓ 組み合わせる ↓ 顧客データ

はデータ統合。

CRMからDWHへデータを運ぶ部分はデータ取り込みです。

  • Internal Ingestion(内部統合)はここでは別扱い

同じシステム内部で、

Table A → Table B ストレーム→ キャッシュ のようにデータを移すこともあるが、この本ではそれを主にデータ変換の一部 として扱う。

Chapter 7のデータ取り込みは、主にソースシステムからデータエンジニアリング側へ持ってくる部分。

*データパイプラインはデータ取り込みより広い概念

データ取り込みはパイプラインの一部。

データパイプラインは、

アーキテクチャ + システム + プロセス

を組み合わせて、データをデータエンジニアリングライフサイクル全体に流す仕組み。

つまり、

Source ↓ Ingestion ↓ Storage ↓ Transformation ↓ Analytics / ML / Serving

全体がデータパイプライン。

  • ETL / ELT / Reverse ETLも全部パイプラインのパターン

ETLやELTを別物として強く区別しすぎるのではなく、現代では

「目的に応じて適切なツールとパターンを組み合わせる」

ことが重要。

Reverse ETLやデータシェアリングも、広い意味ではデータパイプラインの一部として扱える。

  • モダンデータパイプラインは柔軟であるべき

昔はMonolithic ETLのように、 決まったシステム・決まったフロー が中心だった。

今はクラウドサービスやツールをLEGOのように組み合わせ、

100 Sourceから取得 ↓ 20 Tableに統合 ↓ ML ModelをTraining ↓ ProductionへDeploy ↓ Monitor

のような複雑なワークフローもデータパイプラインに含まれる。

ingestの軸

まずユースケースと目的地を決める

Ingestionでは最初に、 何のためのデータか / どこへ送るか / どれくらいの頻度で更新するか / どれくらいの量か を考える。

さらに、 フォーマット / データの質 / 下流との互換性 / ストリーミング時の前処理 も確認する。

つまり「とりあえず全部取り込む」のではなく、下流でどう使うかから逆算してIngestionを設計する。

  • Bounded vs Unbounded Data

Unbounded Data → 終わりのない継続的なEvent Stream。

例:

Web click IoT sensor Orders Logs

Bounded Data → 時間などの境界で区切られた有限データセット。

例:

2026-09-17の注文 1時間分のLog

本文の重要な考え方は、

“All data is unbounded until it’s bounded.”

実世界ではデータは継続的に発生していて、Batchとはそれを人工的に区切っているだけ、という発想。

Frequency:Batch / Micro-batch / Streaming

Ingestion頻度は連続的なスペクトラム。

Batch → 1日1回、1時間1回などまとめて処理

Micro-batch → 数秒〜数分程度の小さなBatch

Streaming / Near Real-time → イベントが来たらほぼ即時処理

完全なReal-timeは存在せず必ずレイテンシがあるので、正確には Near Real-time。

またStreamingで取り込んでも、下流がBatchなら、そこがパイプライン全体のレイテンシボトルネックになる。

  • Synchronous vs Asynchronous Ingestion

Synchronous

A完了 ↓ B開始 ↓ C開始

各ステージが強く依存している。

一部がfailすると下流が止まり、場合によっては最初から再実行になる。

Asynchronous

イベント ↓ キュー / ストリーム ↓ 各ステージが独立して処理

データが到着したものから並列で処理できる。

キューやストリームが バッファ / ショック吸収 になり、Burst Traffic(一時的な大量データ)も吸収できる。

本文では基本的に、強いSynchronous Couplingを避けてAsyncに寄せる方が柔軟という考え方。

  • Serialization(シリアライゼーション) / Deserialization(デシリアライゼーション)

Ingestionではソースデータをネットワークやストレージへ送れる形式にシリアライズ し、データ受け取り側で デシリアライズ する。

重要なのは、 データ受け取り側がそのフォーマットをちゃんと読めるか を確認すること。

データは届いたのにデシリアライズできず使えない、という状態は避ける。

  • スループット / スケーラビリティ

Ingestion Systemがどれだけのデータ量を処理できるか。

通常時だけでなく、 Backfill / Burst / Source復旧後の大量流入 に耐えられるかを見る。

例えばソースDBが1時間落ちて、その後溜まったデータが一気に流れてくる場合、

通常 1,000 events/s ↓ 復旧後 10,000 events/s

のような状況が起こる。

そのため バッファ + 水平スケーリング が重要。

可能ならマネージドサービスでオートスケーリングさせる。

  • 信頼性 vs 耐久性

信頼性 → Ingestion System自体が安定して動くか

耐久性 → データを失わないか

例えばIoT Deviceがイベントを再送できない場合、Ingestion Systemが落ちるとデータそのものが永久に失われる。

そのためIngestionの信頼性が、そのままデータの耐久性に直結する。

ただしMulti-AZ / Multi-Region / 24時間On-callなどを増やすほどコストも上がるので、どこまで守るかはトレードオフ。

  • ペイロード

ペイロードとは 実際に運ぶデータそのもの。

主に見るのは、 Kind / データの形 / サイズ / スキーマ / データの型 / メタデータ。

例えば、

Kind → Table / Image / Video / Text

Shape → Rows × Columns、JSON Nesting、画像Resolutionなど

Size → 数KBなのか数TBなのか

Schema → カラム名・データタイプ・Nested Structureなど

ペイロードの性質によって、最適なIngestion方法が変わる。

大きなPayloadはChunking(かたまりに分割)する

巨大ファイルはそのまま送るより、

huge_file ↓ chunk1 chunk2 chunk3 ↓ データ受け取り側で再構築

のように分割することがある。

ネットワーク転送しやすくなり、並列処理もしやすい。

  • スキーマ変更に備える

ソース側では、 列追加 / 型変更 / テーブル追加 / 列のリネーム が普通に起こる。

Ingestionツールが自動検知・自動反映できても、下流のレポートやモデルが壊れる可能性がある。

なので、

オートメーション + アラート + 人間のコミュニケーション

が重要。

「自動で通ったから問題なし」ではない。

  • Schema Registry(スキーマレジストリ)

ストリーミングでは生成者と消費者の間でメッセージスキーマを共有する必要がある。

スキーマレジストリは、 スキーマ / データ型 / バージョン / 履歴 を管理するメタデータリポジトリ。

これにより生成者と消費者で、 同じシリアライゼーション / デシリアライゼーション前提 を保ちやすくなる。

  • メタデータ

ペイロード本体だけでなく、 スキーマ / ソース / 日付 / 所有者 / リネージュ などのメタデータも重要。

メタデータがないと、データレイクが「何のデータかわからないData Swamp」になりやすい。

  • Push / Pull / Poll

Push → ソースがデータ受け取り側へデータを送る

Source → Destination

例:Webhook、Event Stream

Pull → データ受け取り側がソースから取りに行く

Destination → Source

例:APIからData取得

Poll → データ受け取りが定期的にソースを確認し、変更があればPullする

1分ごとに確認 ↓ 変更あり? ↓ Pull

Pollingは簡単だが、頻繁すぎると無駄なリクエストが増え、遅すぎるとレイテンシが増える。

Batch取り込みの基本
  • Batch Ingestionの基本

Batch Ingestionは、データをあるまとまりで一括して取り込む方式。

区切り方は主に2つ。

Time-based → 1時間ごと、1日ごとなど時間で区切る

Size-based → 100MBごと、10万イベントごとなど量で区切る

特にストリーミングデータをオブジェクトストレージへ落とす場合、最終的にはFile/Object単位にまとめる必要があるため、Size-based Batchがよく使われる。

  • Full Snapshot vs Differential / Incremental

Full Snapshot → 毎回ソースシステム全体の現在状態を取得する。

実装は単純だが、データ量・ネットワークコスト・ストレージコストが大きくなりやすい。

Differential / Incremental → 前回以降に追加・変更されたデータだけ取得する。

効率はよいが、どこまで取得済みかを正しく管理する必要がある。

つまり、

Snapshot = Simpleだが重い Incremental = Efficientだが管理が複雑

  • File-based Export / Ingestion

ソースDBへ直接接続せず、ソース側でデータをファイル化して渡す方式。

ソースDB ↓ export CSV / Parquetなど ↓ S3 / SFTP / SCP ↓ Destination

ソース側が「何をExportするか」をControlできるため、セキュリティやプロダクトDBへの負荷管理でメリットがある。

本文では、ソース側からファイルを用意して送るので Push Pattern として扱っている。

  • ETL vs ELT

共通するのは、

Extract → ソースからデータを取得

Load → データ受け取り側へデータを保存

違いはTransformationのタイミング。

ETL Extract → Transform → Load

ELT Extract → Load → Transform

Load時には、Destinationのスキーマや性能特性を意識する必要がある。

  • バッチサイズはストレージ特性に合わせる

バッチシステムでは、小さいWriteを大量に行うと性能が悪化することがある。

特に列指向データベースでは、

1 row insert 1 row insert 1 row insert ...

のような処理は、小さいFile/Objectを大量に作ってしまい非効率。

小さいUpdateを大量に行うのも、既存列ファイルのスキャンが必要になって重くなりやすい。

そのため、 ストレージエンジンに適したバッチサイズとWrite Patternを理解することが重要。

  • ツールによって得意なWrite Patternが違う

例えば本文では、

Druid / Pinot → High Insert Rateに強い

SingleStore → OLTP + OLAPのHybrid

BigQuery → SQLで大量のSingle-row Insertは苦手だが、Streaming Buffer経由なら強い

といった違いがある。

つまり、同じ「Insert」でもシステムごとに正しい入れ方が違う。

  • データ移行

データベースや環境を移行するときは、大量データをバルクで移す必要がある。

重要なのはデータ量だけでなく、スキーマの互換性。

SQL Server → Snowflakeのように似たデータベースでも、 データタイプやスキーマの扱いに細かな差がある。

そのため、いきなり全量を移すのではなく、サンプルデータで先にテストするのが重要。

  • 移行ではデータよりパイプライン接続の移行が難しいこともある

データベースそのものを移せても、

Old DB ↑ ↓ Pipeline A Pipeline B Dashboard Application

など、Old Systemにつながっている依存関係をNew Systemへ切り替える必要がある。

そのためデータ移行では、データコピーだけでなく依存関係 / データ間の関係の移行まで考える。

  • Direct Database Connection:ODBC(Open Database Connectivity,アプリケーションから異なる種類のデータベースに共通の書き方でアクセスできるようにする) / JDBC(Java Database Connectivity,)

データベースへ直接接続してクエリし、データを取り出す方法。

ODBC / JDBC はデータベースごとの差をドライバが吸収して、標準的なインタフェースで接続できる。

JDBCはJVM上で動くため携帯性が高く、Sparkなどでもよく使われる。

ただし大量データ取得では、並列クエリを増やすほどソースデータベースへの負荷も増えるので注意。

  • JDBC / ODBCの限界

これらは基本的に 行形式 でデータを送るため、列指向データベースやネストデータとの相性がよくない。

そのため最近では、 Parquet / ORC / AvroへのDirect Export やREST APIなどを使う場合も多い。

実務では、

ソースデータベース ↓ JDBC リーダー ↓ オブジェクトストレージ ↓ ターゲットDWH

のように、JDBCだけで完結せず他のデータ取り込み方式と組み合わせることが多い。

  • CDC(変更データキャプチャ):変更だけを取り込む

CDCはソースデータベース INSERT / UPDATE / DELETE を取得する仕組み。

バッチCDC → updated_at などで前回以降の変更行を取得

継続的CDC → データベースログを読んで、変更をイベントとして継続的に取得

継続的CDCならニアリアルタイムに近い複製やストリーミング分析ができる。

バッチCDCの弱点

updated_at だけを見るバッチCDCでは、 途中で何回変更されたかという履歴を失う。

例えば残高が1日に5回変わっても、最後の残高しか取れない。

完全な履歴が必要なら、 Insert-only設計やログベースCDC の方が向いている。

  • CDCと複製

Synchronous Replication(同期レプリケーション) → プライマリーとレプリカを完全同期 → リードレプリカとして使える

Asynchronous CDC(非同期CDC) → 少し遅延してもよい代わりに疎結合

プライマリDB ↓ CDC ストリーム ├→ レプリカ ├→ オブジェクトストレージ └→ リアルタイム分析

のように複数データ出力へ流せる。

分析用途では、この柔軟性が大きい。

  • API Ingestion

SaaSなどからデータを取る一般的な方法。

ただしAPIは標準化が弱く、 認証 / ページネーション / レートリミット / スキーマ / エラーハンドリング などを個別に理解する必要がある。

そこで、 Client Library / マネージドコネクタ / データシェアリング をできるだけ使って、カスタムコネクタ開発を減らす。

  • マネージドデータコネクタ

データベースやAPIごとのコネクタをVendorやOSSに任せる方法。

通常は、 ソース / Destination / Credential / Sync Frequency / CDC方式 を設定するだけでデータシンクできる。

エラー時の監視やアラートも提供される。

本文の立場はかなり明確で、 コネクタ作成は無駄な労働からの解放がメインなので、可能ならマネージドサービスを使うべき というもの。

メッセージキュー/ イベントストリーミング

リアルタイム取り込みではキューやストリームを使う。

メッセージキュー → メッセージ単位で処理し、ACK後は消える

ストリーム → 順番付きログとして保持し、再読込や再処理ができる

ストリーミングでは、 Publish → Consume → Transform → Republish のようにデータフローが非線形になりやすい。

またスループット / パーティション / CPU / メモリー / オートスケーリングを考える必要がある。

  • オブジェクトストレージを使ったデータトランスファー

大量ファイルをやり取りするなら、 S3 / GCS / Azure Blob のようなオブジェクトストレージが非常に相性がよい。

特徴は、 高スケーラビリティ / セキュリティ / 信頼性 / 任意ファイルフォーマット対応。

チーム間や企業間でのファイル交換にも向く。

  • データベースファイルエクスポート

ソースDBからCSVやParquetなどへバルクエクスポートして取り込む方式。

大量スキャンは製品DBに負荷をかけるため、 時間帯をずらす / パーティション単位でエクスポート / 読み取り用複製DBを使う などの対策が必要。

クラウドデータウェアハウスではオブジェクトストレージへの直接エクスポートがかなり最適化されている。

  • CSVは便利だが危険

CSVは非常に普及しているが、 Delimiter / Quote / Escape / Encoding / Schema が曖昧。

スキーマも内包しないため、製品では自動検出に頼りすぎない方がよい。

一方、 Parquet / Avro / ORC / Arrow / JSON はスキーマを持てて、Nested Dataも扱いやすい。

特に列指向分析ではParquet / ORC / Arrowが相性がよい。

Shell / SSH / SFTP / SCP

小規模なIngestionならシェルスクリプトでも十分実用的。

例えば、

DBからExtract ↓ ファイル変換 ↓ S3 Upload ↓ Target Load

をCLIだけで実装できる。

SSHはデータベースへのセキュアトンネルやSCPに使える。

SFTPも古いが、企業間データ移行では今でも現役。

Webhook

普通のAPIは消費者がソースへ取りに行くが、Webhookは逆。

Source ↓ HTTP POST Consumer Endpoint

なので Reverse API と呼ばれる。

実用的なアーキテクチャでは、

Webhook ↓ Lambda ↓ Kinesis ↓ Flink ↓ S3

のように、受信・Buffer・Proc。essing・ストレージを分離することが多い。

  • Web UI / Webスクレイピング

APIがない場合、Web UIからFileを手動ダウンロードすることもあるが、 人依存なのでAutomateできるならAutomateするべき。

Webスクレイピングは最後の手段に近く、 DoS防止 / Rate Control / ToS / Legal Risk / HTML変更による保守負荷 を考える必要がある。

  • Transfer Appliance

100TB以上の非常に大量データでは、インターネット転送より 物理ディスクをCloud Vendorへ送る方が速く安い 場合がある。

AWS Snowball / Snowmobileなど。

これは継続Ingestionではなく、One-time Migration向け。

  • データシェアリング

Snowflake / BigQuery / Redshiftなどでは、データを物理コピーせずに共有できる。

厳重な意味ではIngestionではないが、 データを使える状態にする手段 として非常に重要。

ただし自分がデータを所有しているわけではないので、プロバイダにアクセスを切られると使えなくなる。

  • ingestのプロセスについて

上流ステークホルダとの連携

ソースデータを作るのは多くの場合ソフトウェアエンジニアで、データエンジニアとは別チームにいる。

問題は、ソフトウェアエンジニア側がデータエンジニアを単なる下流消費者として見がちなこと。

そこでデータエンジニアは、 スキーマ変更の共有 / イベント設計 / データの質改善 /リアルタイムアーキテクチャ などを一緒に進める必要がある。

特に重要なのは、ソース側で質を改善すること。

  • 下流ステークホルダをカスタマーと考える

データサイエンティストやアナリストだけでなく、 マーケティング / サプライチェーン / 管理職 などビジネスユーザーもカスタマー。

高度なストリーミングプラットフォームを作ることより、 Google Ads Reportの手動ダウンロードを自動化する 方がビジネスバリューが高い場合もある。

つまり、技術的な熟練度より 実際のビジネスへのインパクトを優先する。

  • コミュニケーションが中心

上流にも下流にも共通する重要語がコミュニケーション。

スキーマ変更、データ定義、パイプライン変更などを早期に共有することで、手戻りを減らせる。

データエンジニアはシステム間だけでなく、組織間のインターフェース設計でもある。

  • セキュリティ:Data in Motionを守る

Ingestionではデータをネットワーク越しに動かすため、セキュリティリスクが増える。

基本は、 VPC内はPrivate Endpoint On-prem ↔ CloudはVPN / Private Connection パブリックなインターネットを通るなら暗号化 。

ストレージ時だけでなく、Transfer中の暗号化も重要。

スキーマ変更は「厳しすぎても緩すぎてもダメ」

変更承認に半年かかるようなCommand-and-Controlでは機敏性が死ぬ。

逆にソーススキーマ変更をそのままTargetに自動反映すると、下流が壊れる。

本文ではGitのBranchに近い考え方として、 Development Tableで新スキーマを試してからメインへ反映 するような方式を示している。

つまり、スキーマにもVersioning / Staging / Controlled Promotionを持たせる。

  • センシティブなデータは「そもそも取る必要があるか」を考える

Privacyで最も強い対策は、 不要なSensitive DataをIngestしないこと。

取る ↓ Encryptする

より、

不要なら最初から取らない

方が安全。

必要ならTokenization / Hashing / Maskingなどを使う。

  • Touchless Production / Broken-glass

センシティブなデータを扱う製品では、人が直接データに触らない Touchless Production が理想。

Development / StagingではSyntheticやCleansed Dataを使い、ProductionへのDeploymentは自動化する。

どうしても製品データを見る必要がある場合は、 複数人承認 / スコープ限定 / 期限付きアクセス のBroken-glass Processを使う。

  • EncryptionだけではPrivacy問題は解決しない

実際には多くのCloud DBはAt Rest / In Transit Encryptionを標準で備えている。

本質的な問題は、 誰がそのデータへアクセスできるか の方であることが多い。

ハッシュも単純に使えば安全とは限らず、既知のEmailをハッシュして照合できる場合もある。

つまり、セキュリティコントロールは技術を置くだけでなく攻撃シナリオまで考える。

  • DataOps:Ingestionは特に監視が重要

Ingestionが止まると、 DWH / Data Lake / Report / ML Model 全部の更新が止まる。

最低限見るべきなのは、 Uptime / Latency / Data Volume / Event Rate / Event Size。

さらに、 Event Time / Ingestion Time / Process Time / Processing Time を追跡すると、どこでLatencyが起きているか分かる。

Third-party Dependencyも監視する

マネージドサービスを使えばオペレーション負荷は下がるが、そのシステムは自分ではコントロールできない。

そのため、 Outage Alert / Failover / Incident Response Plan を考える必要がある。

「マネージドだから止まらない」ではない。

  • データ質のテスト

データはコードと違い、自分たちが何もデプロイしていなくても壊れる。

例えば、 Null増加 / Category追加 / Distribution変化 / Bot Traffic増加 など。

そのため、 バイナリーチェック + 統計的な監視 が必要。

特に危険なのはパイプラインが落ちることではなく、間違ったデータが正常そうに流れ続けること。

  • データの質はソースで直すのが理想

下流でクリーンし続けるより、 ソフトウェアエンジニアと協力してソース側で、 Validation / Logging / Exception Handling を入れる。

データの質はデータチームだけの責任ではない。

  • オーケストレーション

IngestionはData Pipelineの一番上流にあり、その後に多数のTaskが依存する。

小規模ならCronでも動くが、複雑になると脆い。

本格的には、 Task Graph / Dependency / Retry / Scheduling を扱えるOrchestratorが必要。

Ingestion完了 ↓ Transformation ↓ Aggregation ↓ Serving

のように依存関係を管理する。

  • ソフトウェアエンジニア

Ingestionは外部システムとの接点が多く、かなりエンジニアリング的に負担が重い。

マネージドコネクタを使えるところは使い、 カスタムコードを書くなら、 Version Control / Code Review / Testing / CI/CD を適用する。

またソースやデータ取り込み側に強く依存したモノリスな設計を避け分離された設計にする。

Fundamentals of Data Engineering 6章

今度はストレージについて

ストレージのシステムの説明
  • ストレージはデータエンジニアリングライフサイクルの土台

データは Ingestion(取り込み) → Transformation(データ加工) → Serving(データ提供) の各段階で何度も保存される。

ストレージ選定で最初に考えるべきなのは、 「このデータを将来どう使い、どう取り出すか」。

つまり、ストレージは単に「保存できればいい」のではなく、アクセスパターンに合わせて選ぶ必要がある。

  • ストレージは3層で考える

この本の中では、

生データ → HDD / SSD / RAM / Network / CPU / Serialization(シリアライズ) / Compression(圧縮)

ストレージシステム → それらを組み合わせた実際のストレージシステム

ストレージ抽象化(物理的なハードウェアを隠し、統一的なインターフェースで管理する) → データレイク / クラウドデータウェアハウス など

という構造で考えている。

データエンジニアは普段HDDを直接触らなくても、下の物理特性が上位システムの性能・コストを決めるので理解が必要。

  • HDD:安いがランダムアクエスが遅い

HDDは物理的なディスクを回転させ、ヘッドを移動してデータを読む。

そのため、 シークタイム(探す時間) / Rotational Latency(回転待ち時間) / 低IOPS(Input/Output Operations Per Second,読み書きの速さ) という物理的な制約がある。

一方で 容量単価が非常に安いため、大量データ保存には今でも重要。

クラウドオブジェクトストレージでは大量のHDDを並列に読むことで、1台の遅さを補っている。

  • SSD:高速ランダムアクセスに強い

SSDは機械的な動作がないため、 低レイテンシ / 高IOPS / 高Transfer Speed が特徴。

そのため、PostgreSQLやMySQLなどの OLTP に非常に向いている。

ただしHDDよりかなり高価なので、大規模分析データをすべてSSDに置くのはコストが高い。

OLAPでは、よく使うデータだけSSDキャッシュに置くこともある。

RAM:さらに高速だが揮発性・高価

RAMはSSDよりさらに高速で、CPUが直接処理するデータを置く。

ただし、 Volatile(電源が切れると消える) という大きな特徴がある。

そのため、 キャッシュ / データ処理 / インデックス には適するが、Durable Storage(データを持ったまま消えないストレージ)として使う場合は複製やディスクへの退避が必要。

  • ネットワーク / CPUもストレージ性能を決める

現代のストレージは分散システムなので、ディスク性能だけではなく、 ネットワーク帯域 / ネットワークレイテンシ / CPU も重要。

データを複数ゾーンに分散すれば耐久性や可用性は高まる一方、 レイテンシやネットワークコストが増える。

つまり、耐久性・可用性 vs パフォーマンス・コストのトレードオフがある。

  • シリアライズ

メモリー上のデータを、 ディスク保存やネットワーク転送できる標準フォーマットへ変換すること。

例: JSON / CSV / XML / Parquet / Arrow

シリアライゼーション形式は、 相互運用性 / CPU Cost / クエリパフォーマンス / 圧縮効率 に影響する。

例えば、 Row-oriented(行指向) は1Record単位のLookupやUpdateに向き、 Column-oriented(列指向) は大量スキャンや圧縮に向く。

  • 圧縮

データを小さくすることで、

ストレージコストを下げる ディスクスキャンを実質高速化する ネットワーク転送量を減らす

というメリットがある。

ただし圧縮 / 展開にはCPUのコストがかかる。

つまり、ストレージ・ネットワークの節約 vs CPU負荷のトレードオフ。

  • キャッシュ

よく使うデータを高速で高価なストレージに置き、あまり使わないデータを安く遅いストレージに置く。

典型的なヒエラルキーは、

CPUキャッシュ → RAM → SSD → HDD → オブジェクトストレージ → アーカイブストレージ(さらに安いけど取り出す時間長い)

と下に行くほど、遅く・安く・大容量になる。

実際のデータシステムは、この複数レイヤーを組み合わせている。

  • アーカイブストレージはリバースキャッシュ

アーカイブは非常に安価だが、取り出すまで数時間かかるようなストレージ。

バックアップやコンプライアンスなど、 普段は読まないが、長期間残しておく必要があるデータに使う。

例えば障害復旧や、先ほど出てきたリーガルチェック のための過去データ保存。

ストレージシステムの中身

シングルマシンvs 分散ストレージ

データ量やアクセス量が増えると、1台のサーバーだけでは限界が来るので、複数サーバーへデータを分散する分散ストレージを使う。

メリットは、 スケーリングできる / 冗長性 / 並列処理 / 耐障害性。

一方、複数ノードにデータを複製するため、一貫性をどう保つかが問題になる。

結果整合性 vs 強整合性

結果整合性 → 一時的には古いデータが返る可能性があるが、最終的には全ノードが同じ状態になる。 高速・大規模な分散システムと相性が良い。

強整合性 → Write後のReadでは必ず最新データが返る。 正確性が高い代わりに、ロックや同期などが必要でレイテンシやコストが増えやすい。

つまり、

スピード / スケーラビリティ↔ 一貫性

のトレードオフ

  • ファイルストレージ

ファイルは、 有限長 / Append可能 / ランダムな読み書き可能 という特徴を持つ。

普通のファイルシステムでは、

/users/data/output.csv

のようなディレクトリツリーでファイルを管理する。

Local Disk、NAS(Network Attached Storage)、Cloud Filesystemなどがこの系統。

Local Disk / NAS / Cloud Filesystem

Local Disk → 1台のマシンに直接接続。高速だが、そのマシンへの依存が強い。

NAS → ネットワーク越しにファイルシステムを共有。複数マシンから同じファイルを扱える。

Cloud Filesystem → NASのマネージド版。Amazon EFSなど。

Cloud VendorがDisk、Replication(複製バックアップなど)、Failure Handlingなどを管理する。

  • ブロックストレージ

HDDやSSDを、細かい ブロック単位 でRead / Writeするストレージ。

ランダムアクセス性能が高いので、 OLTP DatabaseやVMのBoot Disk に向いている。

AWSならEBSが代表例。

EBSはEC2本体とは別にデータが保存されるため、インスタンスを停止・削除してもデータを残せる。

  • ローカルインスタンスストレージ

VM Hostに直接付いているディスク。

低レイテンシ・高IOPS・安価 だが、 VM停止やホスト障害でデータが消える可能性がある。

そのため永続的なストレージではなく、 キャッシュ / データ処理用 に向く。

例えばS3からデータを読み、EMRで一時処理して、結果をS3へ戻すような使い方。

  • オブジェクトストレージ

S3 / GCS / Azure Blobなど。

データを オブジェクト = Key + Data として管理する。

ファイルストレージとの大きな違いは、 基本的にObjectをIn-placeで変更できないこと。

オブジェクトを書き込む → 不変 → 変更したいならオブジェクト全体を書き直す

Appendや細かいランダムな書き込みには向かない。

  • オブジェクトストレージがデータエンジニアリングに向く理由

オブジェクトストレージは、 大量データを安価に保存できる / ほぼ無限にスケールする /並行読み書きに強い / 高耐久性 という特徴を持つ。

そのため、 データレイク / Cloud DWH / ML生データ の主要ストレージになっている。

逆に、 毎秒大量の小さなUpdateをするOLTP には向かない。

オブジェクトストレージは本当のディレクトリを持たない

例えば、

s3://bucket/project/2026/09/data.csv

はディレクトリ構造に見えるが、実際には

key = project/2026/09/data.csv

という1本のKey。

つまりS3のフォルダーは実体ではなく、Key Prefixをディレクトリっぽく見せているだけ。

そのため大量オブジェクトがあると、ディレクトリ相当のリスト化が高コストになる場合がある。

  • Object Versioning / Lifecycle Policy

オブジェクトを同じKeyで書き直すと、新しいVersionとして保存できる。

Versioningを使えば、 過去Versionへ戻す ことが可能。

ただしVersionごとにFull Objectを保存するので、ストレージコストが増える。

そこでLifecycle Policyを使って、 古いVersionをDelete / Archive することが多い。

  • Storage Classes / Archive

オブジェクトストレージにはアクセス頻度に応じたティアがある。

例えばS3なら、 Standard → Infrequent Access → Glacier → Deep Archive のように、

アクセスしにくくなるほどストレージコストが安くなる。

Deep Archiveは非常に安い代わりに、復元に数時間かかる。

つまり前に話した、 オブジェクトストレージとアーカイブストレージの違い は、このStorage Tierの違いとしても理解できる。

  • キャッシュ / メモリーストレージ

RAMベースのストレージは超高速だが揮発性がある。

Memcached → SimpleなKey-Value Cache

Redis → Key-Valueに加えListやSetなどを扱え、SnapshotやJournalによるPersistenceも可能。

データベースやAPIの負荷を減らし、Ultra-low Latencyでデータを提供するときに使う。

HDFS

Hadoop Distributed File System。

大きなFileをBlockに分割し、複数NodeにReplicationして保存する。

特徴は、 ストレージと演算を同じクラスタに置く こと。

これはS3などのオブジェクトストレージとは大きく異なる。

現在は、 Storage = S3 Compute = Spark / EMRなどのEphemeral Cluster と分離するアーキテクチャが増えている。

  • ストリーミングストレージ / Replay

KafkaなどではEventを一定期間保存できる。

過去のEventを再度読み直すのが Replay。

Event Stream ↓ 過去のOffsetに戻る ↓ 再処理

パイプライン障害後の再処理や、過去データを使ったバッチプロセシングに使える。

  • インデックス

テーブル全体をスキャンせずに、特定レコードを高速に探すための「検索用Map」。

OLTPではPrimary KeyやForeign Keyなどにインデックスを作ることで、 高速なLookup / Update が可能になる。

ただし分析では大量行をスキャンするので、インデックス中心とは違う方法が使われる。

  • 行ストレージ vs 列ストレージ

行ストレージ → 1行がまとまって保存される → 1レコード単位のLookup / Updateに強い

列ストレージ → 同じ列のデータをまとめて保存 → 分析の大量スキャンに強い

列ストレージは、 必要カラムだけ読む / 同じ種類の値が並ぶので圧縮しやすい というメリットがある。

  • パーティショニング/クラスタリング

列ストレージでもテーブル全体をスキャンすると重いので、データをさらに整理する。

パーティショニング → テーブルを大きな単位で分割する。

例:

date=2026-09-14 date=2026-09-15 date=2026-09-16

クラスタリング → パーティション内部で、特定カラムの値が近いデータをまとめる。

これによりフィルタリング / Join / Sortを高速化できる。

  • Snowflake Micro-partitioning

Snowflakeではテーブルを自動的に マイクロパーティション に分割する。

各Micro-partitionには、 列ごとのMin / MaxなどのMetadata が保存される。

例えば、

WHERE created_date = '2026-09-16'

とすると、その日にちを絶対に含まないMicro-partitionを読まない。

これが Pruning。

つまり、

全データを読む

のではなく、

メタデータを見る ↓ 関係ないMicro-partitionを除外 ↓ 必要な部分だけスキャン

としてクエリを高速化している。

Storage Abstraction(ストレージ抽象化)を選ぶ判断軸

まず見るのは、 Purpose / Update Pattern / Cost / ComputeとStorageの分離 です。

つまり、 何に使うか / どう更新するか / いくらかかるか / Computeを独立してScaleできるか で選ぶ。

最近はComputeとStorageの分離が進み、データウェアハウスとデータレイクの境界がかなり曖昧になっている。

  • データウェアハウス

分析向けのOLAP ストレージ/クエリ基盤。

昔は専用MPP Database中心だったが、現在はBigQueryやSnowflakeのようなCloud DWHが中心。

Structured / Semistructured Dataを大量に扱えるが、画像・動画・音声のような完全なUnstructured Dataは苦手。

その場合はオブジェクトストレージと組み合わせる。

  • データレイク

大量の生データを加工せず、そのまま長期保存する場所。

もともとはHadoop中心だったが、現在は

オブジェクトストレージ + Compute/Storage Separation

が主流。

ただし初期のレイクでは、スキーマ管理やUpdate/Deleteなどが弱く、扱いづらかった。

  • データレイクハウス

データレイクの安価・柔軟なストレージに、データウェアハウスの管理機能を加えたもの。

オブジェクトストレージ上にデータを置きつつ、 テーブル/ スキーマ / Update / Delete / Incremental Update / History / Rollback を提供する。

Delta Lake、Apache Hudi、Apache Icebergなどが代表例。

つまり、

レイクの自由度 + ウェアハウスの管理性

を狙ったアーキテクチャ。

レイクハウスの大きな強みは相互運用性

Open File Formatでデータを持つため、複数ツールから同じデータを直接読める。

Proprietary Databaseの内部形式だと、別ツールで使うためにデータを変換・コピーする必要があるが、レイクハウスなら

Tool A ─┐ Tool B ─┼→ Metadata Layer → Object Storage Tool C ─┘

のように共有しやすい。

つまり Vendor Lock-inを減らしやすい。

レイクハウスでは全部をテーブル化する必要はない

データレイクハウスでも、生データや非構造化データはそのまま保持できる。

必要なデータだけ、

生データ ↓ テーブル / スキーマを付与 ↓ 分析

とできる。

この柔軟性がウェアハウスとの違いの一つ。

  • データプラットフォーム

ストレージだけでなく、 Ingestion(データ取り込み) / Transformation(データ変換) / Governance / 分析 / ML などのツール群をまとめたVendor Ecosystem。

便利で統合しやすい一方で、 閉じたガーデン化してしまい、Vendor Lock-in(依存が強い)になってしまう可能性 がある。

なので「全部揃っている」ことだけでなく、外部ツールとの相互運用性を見る必要がある。

  • Stream-to-Batch Storage

ストリーミングデータをリアルタイム処理しながら、同じデータをバッチストレージにも保存するアーキテクチャ。

例えば、

Event Stream ├→ Real-time Processing └→ S3などへ保存 → Batch Analytics

という構成。

BigQueryではStreaming Bufferに入ったデータを、その後行指向ストレージへ変換しつつ、両方を透過的にクエリできる。

ストレージ設計について
  • データカタログ

組織内のデータについての メタデータを一元管理する仕組み。

保存するのはデータそのものではなく、 どんなデータがあるか / どこにあるか / 誰が所有者か / どう繋がっているか といったメタデータ。

データウェアハウス、レイク、運用データベースなど横断で管理する。

カタログの主な役割

自動スキャン → 各システムからスキーマやメタデータを自動収集

リネージュ / データの関連性 → Dataがどこから来てどこへ行くか管理

Search / Portal → 人がデータを検索・発見できる

Social Layer → Wikiのように説明・所有者・説明を追加

つまり、データカタログはデータ発見性を支える中心的な仕組み。

  • データシェアリング

特定のデータを、特定の相手に、適切な権限付きで共有する仕組み。

チーム間や企業間でデータを安全に共有できる一方、クラウドのマルチテナント環境では 誤共有・Data Exfiltration(データ流出) を防ぐアクセスコントロールが重要。

  • Schema on Write vs Schema on Read

Schema on Write → データを書き込む時点でスキーマに適合させる。 DWH的な考え方で、後から使いやすく品質も保ちやすい。

Schema on Read → まずデータを柔軟に保存し、読むときにスキーマを解釈する。 データレイク的で柔軟だが、将来の利用時に複雑になりやすい。

ParquetやJSONのようにスキーマ情報を持つフォーマットはSchema on Readと相性がよく、CSVはスキーマの曖昧さが問題になりやすい。

つまり、

Write時に厳しくするか、Read時に柔軟に解釈するか のトレードオフ。

  • ComputeとStorageのコロケーション

昔は、データの近くでComputeすることでネットワーク転送を減らし、パフォーマンスを上げる設計が主流だった。

例えばHDFS + MapReduceでは、 データブロックがあるノードでMap処理を実行する ことで高速化していた。

OLTPでもストレージをComputeの近くに置くことで低レイテンシを実現する。

  • Separation of Compute from Storage

現在のCloudでは、

Storage = S3などに永続化 Compute = 必要なときだけ起動

が主流。

最大のメリットは、 Ephemerality(データ保持が一時的でいい) / Independent Scaling(独立なスケーリング) / Pay-as-you-go。

大きなバッチjobのときだけ巨大クラスターを立て、終了後に消せるので、24時間サーバーを持つ必要がない。

またオブジェクトストレージ側にデータを置くことで、Computeクラスターが壊れてもデータは残る。

実際には完全分離ではなくHybrid

StorageとComputeを完全に離すとネットワークアクセスが遅くなるため、現実にはキャッシュやローカルストレージを組み合わせる。

例えばEMRでは、

S3 ↓ 一時HDFS / SSDで高速処理 ↓ 最終結果をS3へ戻す

Sparkもメモリーやローカル分散ストレージを使って中間データを高速処理する。

つまり、 耐久性のあるストレージは分離し、処理中だけ一時的に合体(連結?)する のが実務的。

  • Zero-copy Cloning

データ本体をコピーせず、ポインタだけ追加して論理的なコピーを作る仕組み。

例えば巨大テーブルでも、実Dataを全部複製しないので高速・低Cost。

ただし元データとUnderlying Fileを共有している場合、元ファイルを消すとクローン側にも影響する可能性がある。

Deep Copyなら実体も全部複製するので安全だが、コストが高い。

  • Hot / Warm / Cold Data

アクセス頻度でデータを分類する。

Hot → 頻繁・即時Access。RAM / SSD。高価。

Warm → 月数回など。オブジェクトストレージの頻繁ではないがアクセスする部分。

Cold → ほぼアクセスしない。Archive / HDD / Tape。非常に安いが取り出しが遅く高い。

基本的に、 アクセス頻度が下がるほど、安く遅いストレージへ移す

というライフサイクルを作る。

  • ライフサイクルポリシー

データの経過年数やアクセス頻度に応じて、自動でStorage Tierを移動する。

例えば、

0〜30日 → Hot 30〜180日 → Warm 180日〜 → Cold / Archive

とすればストレージコストを大きく下げられる。

ただしアーカイブからの復元は時間もコストもかかるので、復旧パターンも考える必要がある。

  • データリテンション

「データをどのくらい保持するか」を決める。

判断軸は、 Value / Time / Compliance / Cost。

再生成できるデータなら長期間持つ価値が低いかもしれないし、規則で一定期間保持が必要な場合もある。

逆にプライバシー性の問題によって「一定期間後に削除」が必要なこともある。

つまり、 “取れるデータは全部永遠に保存”は良い戦略ではない。

  • シングルテナントストレージ

カスタマーごとに完全に独立したストレージを持つ。

Customer A → DB A Customer B → DB B Customer C → DB C

データ隔離が強く、安全性やカスタマーごとのカスタムスキーマに向く。

一方で、テナントを跨いだ分析や統合管理が難しくなる。

  • マルチテナントストレージ

複数カスタマーを同じデータベースやスキーマに入れる。

users ├ tenant=A ├ tenant=B └ tenant=C

インフラ効率がよく、統合分析もしやすい。

一方で、 テナント間のデータ隔離 / Security / Noisy Neighbor(リソース競合) に注意が必要。

ストレージの運用について
  • ストレージは他チームとの責任分担が重要

データエンジニアだけでストレージを完結して管理するとは限らない。

主に関わるのは、 DevOps / Security / Cloud Architect / Ingestion / Transformation Team など。

重要なのは、 誰がインフラをデプロイできるか / 誰がセキュリティを管理するか / 誰がストレージの運用責任を持つか を明確にすること。

組織が成熟するほど、データエンジニアはストレージ全体ではなく一部分を担当することが多くなる。

  • セキュリティ

ストレージでは、 Encryption(暗号化) + Fine-grained Access Control(細かいアクセス制御) + Least Privilege(最小権限の法則) が重要。

データベース全体へのアクセスを簡単に与えるのではなく、 列 / 行 / Cell Level まで必要最小限に絞る。

セキュリティを強化するとデータシェアリングもしやすくなり、結果としてデータの価値を高められる。

  • メタデータ / カタログ / リネージュ

ストレージされたデータは、置いてあるだけでは使いづらい。

データカタログ / メタデータ / データ発見性 / データリネージュ を整備することで、 データの発見 / 問題調査 / Upstream確認 が容易になる。

特にリネージュがあれば、 「この壊れたテーブルはどのソースから来たか」 を追跡しやすい。

  • データバージョニング

オブジェクトストレージのバージョニングを使うと、データ破損や誤更新から復旧しやすい。

MLでも、 どのデータバージョンでモデルをトレーニングしたか を追跡できる。

コードのGit Version Controlと同じように、データにもバージョン管理を持たせるという考え方。

  • プライバシー

GDPRなどに対応するには、ストレージにもライフサイクル管理が必要。

例えば、 特定ユーザーのデータ削除 / マスキング / 匿名化 ができるようにする。

「保存したら終わり」ではなく、後から選択的に消せる設計も必要。

DataOps:システムだけでなくデータ自体を監視する

ストレージモニタリングには2種類ある。

System Monitoring → Capacity / Cost / Security / Access / Infrastructure

Data Monitoring → Data Quality / Distribution / Anomaly / Logical Consistency

例えば行数が急減した、Null率が急増した、値の範囲が突然変わった、といった異常も監視する。

  • データアーキテクチャ

ストレージアーキテクチャでは、 信頼性 / 耐久性 / アクセスパターン / クエリパターン / スケーラビリティ / コスト を考える。

上流でどうデータが作られ、下流でどうクエリされるかを理解してストレージを選ぶ。つまり、どの程度の頻度/分析用なのかなどを考える必要がある。

またFinOpsもアーキテクチャの一部として考える。

基本的には、可能なら フルマネージドシステムを優先し、そのSLA(サービスレベルアグリーメント)を理解する。

  • オーケストレーション

ストレージはデータを保持し、オーケストレーションはそのデータをパイプライン内で動かす。

本文の表現では、 ストレージ = データが流れる経路 オーケストレーション = ポンプ のような関係。

複数のストレージシステムやクエリエンジンをまたぐワークフローをオーケストレーションがまとめる。

  • ソフトウェアエンジニアリング

ストレージを使うコードは、 正しくRead/Writeする / パフォーマンスを悪化させない / メモリーリークを起こさない ようにする。

またストレージインフラも Infrastructure as Code で管理する。

ComputeとStorageを分離しているなら、

オブジェクトストレージにデータを保持 ↓ 必要な時だけComputeを起動 ↓ 処理終了後Computeを削除

という一時的な構成にできる。

これで終わり。結局ストレージも選ぶ際に、分析用なのか、どの程度の頻度でアクセスするのかを意識して選定し、その上でセキュリティ面でアクセス範囲などの管理、便利さの面でリネージュやカタログなども考えないといけないということ。

Fundamentals of Data Engineering 5章

ようやく具体的な内容に入れる。

データソースのシステムとは
  • ソースシステムを理解することが出発点

データエンジニアは、データを取り込む前に どこで生成されるか / どう書き込まれるか / どんな制約や癖があるか を理解する必要がある。

例えばRDBMSなら、Write・Commit・Queryの仕組みまで知っておくと、インジェスト(データ取り込み)設計で事故を減らせる。

データはアナログ / デジタルの両方から生まれる

アナログデータは音声・紙・現実世界の出来事など。 デジタルデータは、アナログをデジタル化したもの、またはトランザクションやアプリケーションなどデジタルシステムが直接生成したもの。

IoT、Credit Card、Web、Stock Tradeなど、ソースは非常に多様。

代表的なソース:Files / APIs / アプリケーションDB

Files:CSV、Excel、JSON、XML、TXTなど。今でも重要な交換形式。 APIs:System間でDataを取得する一般的な方法。ただしAPIごとの差異やメンテナンスが必要。 アプリケーションDB:アプリケーションの現在状態を保存するデータベース。多くはOLTP。

  • OLTP

Online Transaction Processing は、アプリケーションのバックエンド向けで、低レイテンシ・高い同時実行性・1件単位のRead/Writeに強い。

例えば銀行口座の残高更新やECサイトの注文処理。

一方、大量データをスキャンするアナリティクスには向いていないため、OLTPに直接重い分析クエリを投げ続けるのは避ける。

  • ACIDとAtomic Transaction

ACIDはデータベースが正しい状態を維持するための性質。

Atomicity:全部成功するか、全部失敗する Consistency:整合性のある状態を保つ Isolation:同時処理がお互いを壊さない Durability:Commit済みDataは失われない

例えば銀行振込では、A口座から減額したのにB口座へ加算されない、という状態を防ぐ。

ただし分散データベースではパフォーマンスのために Eventual Consistency(いつ整合するか分からないが、一度不整合を受け入れる) など、一致性を緩める場合もある。

  • OLAP

Online Analytical Processing は、大量データをスキャン・集計する分析向け。

列志向データベースなどが代表的で、 大量スキャンには強いが、1件ずつ高速にLookupする用途には弱い。

OLTPとOLAPは目的がかなり異なるため、一般にはアプリケーション用と分析用を分離する。

  • CDC(Change Data Capture)

データベースで発生したINSERT / UPDATE / DELETEをChange Eventとして取り出す仕組み。

ニアリアルタイムのDBのレプリケーションやEvent Stream作成に使われる。

データベースのログから変更を読む方式が代表的。

  • ログ/ データベースログ

ログはシステムで「何が起きたか」を記録したData。

最低でも、Who / What / Whenを持つのが理想。

Log形式には、Binary / Semistructured(JSONなど) / Plain Textがある。

データベースでは Write-Ahead Log に変更を書いてから処理成功を返すことで、サーバー障害後も状態を復元できる。これはCDCにも利用できる。

  • CRUD と Insert-only

CRUD = Create / Read / Update / Delete アプリケーションDBで最も一般的なデータ操作パターン。

一方 Insert-only ではUpdateせず、新しいバージョンを毎回Insertする。

例えば住所変更なら、

customer=1, Tokyo, 2025 customer=1, Osaka, 2026

のように履歴がそのまま残る。

履歴分析に強い一方、データ量が増えやすく、現在値取得時に最新レコードを探す必要がある。

  • メッセージキューとストリーミングの違い

メッセージはシステム間で渡す1つのシグナル。通常は消費者が受け取ればキューから消える。

ストリームはイベントを順番に追加していく Append-only Log で、一定期間保存される。

そのため、 Message Queue → 処理を依頼・通知する Stream → Event履歴を残して後から分析・リプレイする という違いがある。

https://socprime.com/ja/blog/message-queues-vs-streaming-systems-key-differences-and-use-cases/

  • Timeを分けて考える

ストリーミングでは特に時間の種類が重要。

Event Time:ソースでイベントが発生した時刻 Ingestion Time:データがパイプラインに取り込まれた時刻 Process Time:処理が開始・実行された時刻 Processing Time:処理にかかった時間

これらを記録しておくことで、 データが遅れて届いたのか / 取り込みが遅いのか / 処理が遅いのか を切り分けられる。

ソースシステムについて
  • Databaseを理解するときの共通観点

DBの種類に関係なく、まず見るべきなのは DBMS(データベース管理システム) / Lookup・Index / Query Optimizer(クエリ最適化) / Scaling / Data Modeling / CRUD / Consistency(一致性)。

つまり、 どう保存するか、どう検索するか、どうスケールするか、どんなスキーマが向くか、一致性をどこまで保証するか を理解することが重要。

  • RDBMS(リレーショナルデータベース)

RowとColumnを持つテーブルでデータを管理し、Primary Key(主キー) / Foreign Key(外部キー) / Join / Normalization(正規化)を使う。

一般に ACID + 高いトランザクション性能 + 固定スキーマ を持つため、Applicationの状態管理に向く。

特に正規化によってデータ重複を減らし、複数箇所を更新することで起きる不整合を防ぐ。

データエンジニア側では、現在の状態だけでなく履歴をどうAnalytics側へ持っていくかが課題になる。

  • NoSQL(Not Only SQL)は用途特化型

RDBMSの制約を緩める代わりに、スケール / パフォーマンス/ スキーマの柔軟性を得る。

ただし、強一貫性、Join、固定スキーマなどを失う場合があるため、用途に合うDBの型を選ぶ必要がある。

  • キーバリューDB / Document DB

Key-Value Storeはキーから値を高速に取得する。キャッシュや大規模ステート保存などに向く。

Document StoreはJSONのようなネストドキュメント(層状になっているドキュメント)を保存する。スキーマが柔軟でアプリケーション開発しやすい一方、結合しにくく、同じ情報を複数のドキュメントに重複保存しやすい。

スキーマを自由に変えすぎると、ダウンストリームパイプラインが壊れたりデータが不統一になるので注意。

分析ではフルスキャンかCDC(変更データキャプチャ)で別の分析システムへ送ることが多い。

  • Wide-Column / Graph / Search / Time-Series

Wide-column DB → 超大量Write・低レイテンシ・巨大スケール向け。IoT、Ad Tech、Fintechなど。複雑なクエリは苦手。

Graph DB → ノードと辺で「関係性」を扱う。SNS、人間関係、Fraud Networkなど、複雑なトラバーサルに強い。

Search DB → Full-text Search(全文検索)やLog Analysis向け。Elasticsearchなど。

時系列DB → Timestamp中心の大ボリュームデータ向け。Sensor、Metrics、Logs、Fintechなど。 Measurement DataとEvent-based Dataがある。

要するに、NoSQLは“SQLじゃないDB”というより、特定のアクセスパターンに最適化されたDB群として見る方が分かりやすい。

  • REST API

HTTPを使う最も一般的なAPI形式。 GET / PUTなどでリソースを操作し、各リクエストはステートレス(サーバーが過去の通信内容やクライアントの状態を保存しない設計)。

ただしRESTは厳密な仕様ではないため、APIごとの差異が大きい。 そのためデータエンジニアはAuthentication、Pagination、レートリミット、スキーマ、Sync方法などを理解する必要がある。

クライアントライブラリや既存コネクタがあれば、できるだけそれを使ってカスタマイズされた実装を減らす。

  • GraphQL / Webhook / gRPC

GraphQL → Client側が欲しいデータの型を指定でき、1 Requestで複数モデルを柔軟に取得できる。

Webhook → イベント発生時にソース側からConsumerのHTTP EndpointへPushする。通常APIの逆向きなので Reverse API と呼ばれる。

gRPC → Remote Procedure Call。Protocol Buffers + HTTP/2を使い、高効率な双方向通信に向く。

RESTより強い技術仕様書を持つので、共通ツールやクライアント生成がしやすい。

  • データシェアリング

クラウドDWHやオブジェクトストレージ上で、データそのものをコピーせずに他チームや他テナントへ共有する仕組み。

Row / Column / Sensitive Data単位でアクセスコントロールできる。

これにより、 データマーケットプレイス / 組織内データ共有 / データメッシュ が実現しやすくなる。

特に各領域が自分のデータを管理しつつ、必要な相手だけに共有できる点が重要。

  • サードパーティデータソース

API・クラウドデータシェアリング・Downloadなどを通して、外部企業や政府などのDataを利用する。

典型例はCRM Dataを取得し、 Analytics / Scoring → Reverse ETLでCRMへ戻す といったワークフロー。

データエンジニアにとって、外部データとの統合はかなり一般的な仕事になる。

*メッセージキュー

システム間で小さいメッセージを非同期に送る仕組み。

メッセージ作成者 → キュー → 受信者 で、予約者が通信の合図を送ると通常メッセージは削除される。

マイクロサービスやイベント駆動アーキテクチャで使われ、 Decoupling(疎結合)・・・サービス同士がお互いの状態や実装に強く依存しなくなるようにするのが目的。 Buffering(バッファリング)・・・一時的にメッセージが大量に生成され、メッセージの処理が追いつかない分を吸収するクッション Durability(耐久性)・・・メッセージを受け取ったあと、そのメッセージが消えないようにする。 が主な役割。

特に注意するのは、 Ordering・・・分散システムの場合、処理順がおかしくなると致命的なので、順番をどの程度正確に保つかが大事 Delivery Guarantee・・・メッセージが何回受信されるか。Exactly-once / At-least-once などにより、メッセージを落とさないことと重複しないこと、どちらを重視するか Scalability・・・大量メッセージを並列処理するうえで大事。 Idempotency・・・同じMessageを1回処理しても10回処理しても最終結果が同じという性質。

メッセージデリバリーでは、 Exactly once:1回だけ At least once:1回以上、重複あり得る

という違いがある。

実務では重複が起こり得るため、処理を Idempotent(べき等) にするのが重要。

  • イベントストリーミングプラットフォーム

メッセージキューと似ているが、ストリーミングではデータを一定期間保存するAppend-only Logとして扱う。

そのため、再現 / ヒストリカル分析 / Multiple Consumers(複数の消費者が同時にアクセス)が可能。

イベントは基本的に Key / Value / Timestamp(日時) を持つ。

  • トピック / パーティション イベントは トピックに発行される。トピックは複数作成者 / 消費者を持てる。

トピックはさらにパーティションに分割され、並列処理とスループット(単位時間の処理能力)を上げる。

同じパーティションキーを持つイベントは同じパーティションへ送られるため、デバイス単位などで順序を保ちやすい。

一方で、パーティションキーが偏ると一点にエベントが集中してしまうため、均等に分散するキー設計が重要。

  • ストリーミングの耐障害性

エベントストリーミングプラットフォームは通常分散システムで、複数ノードへ複製される。

そのため一部ノードが落ちても別ノードからデータを読めて、イベントを失わず処理を継続しやすい。

 ソースシステムを扱うときに気をつけるべきこと

ソースシステムのステークホルダーを理解する

データエンジニアが関わる上流ステークホルダは主に2種類。

システムステークホルダー →ソースシステムを作る・運用する人。Software Engineer、Application Developer、外部Vendorなど。

データステークホルダー →データの所有者、アクセス権限を持つ人。IT、Data Governance Team、外部Vendorなど。

重要なのは、上流でスキーマ変更・障害・データ変更が起きたとき、データエンジニアに確実に伝わるフィードバックループを作ること。

  • データコントラクト

ソースシステム側とデータパイプライン側で、どんなデータをどう提供するかを明文化した約束。

例えば、 何のデータを取るか / Full or Incremental(すべてデータを保存するか、新しく変更・追加されたデータだけを保存・処理するか) / 取得頻度 / 担当者 / 連絡先 などを決める。

GitHubや社内Docsなど、誰でも確認できる場所に置き、可能なら標準フォーマットにして自動処理にも使えるようにする。

要するに、 「このソースから、こういうデータがこういう条件で来る」 を曖昧にしないための仕組み。

  • SLA / SLO

SLA(Service Level Agreement) → ソースシステム側と合意するサービス品質の約束。

SLO(Service Level Objective) → SLAを測る具体的な数値目標。

例えば、 SLA:ソースシステムを安定して提供する SLO:Uptime 99%

といった形。

正式なコントラクトが難しくても、Uptime / Data Quality / Freshness / Supportなどの期待値は最低限共有しておく。

  • セキュリティ

ソースシステムへのアクセスで新たな脆弱性を作らないことが重要。

Encryption at Rest / in Transit、VPN、HTTPS、Credential管理、IAM、SSH Key管理 などを確認する。

パスワードやトークンをコードやGitに直接書かず、Secret ManagerやSSOなどを使う。

またソース自体が信頼できるかも確認する。

  • データマネジメント

ソースシステム側でデータがどう管理されているかを理解する。

特に、 Governance / Data Quality / スキーマ変更 / MDM / Privacy / Regulation を確認する。

データエンジニアはソースを直接コントロールできないことが多いので、特にスキーマ変更を事前に通知してもらえる関係が重要。

DataOps

ソースシステムでも障害・デプロイミス・データの質問題は起きる前提で考える。

主に見るのは、 自動化 / 可観測性 / インシデント対応。

例えばソースDBが停止したとき、 パイプラインはどうなるか / アラートされるか / 復旧後にBackfill(再処理)できるか を事前に決めておく。

データチームとアプリケーションチームで監視やインシデント対応を連携させることが重要。

  • データアーキテクチャ

ソースシステム自体のアーキテクチャを変えられなくても、 信頼性 / 耐久性 / 可用性 は理解しておく必要がある。

例えば、 どの程度故障するか / データロスに耐えられるか / いつ利用可能か / 復旧時間はどのくらいか を知ることで、ダウンストリームパイプラインの設計が変わる。

  • オーケストレーション

ソースシステムからデータを取るJobをOrchestrateするときは、 Network Access / Authentication(誰かの確認) / Authorization(その人に与える権限) / Cadence(ソースデータを取るタイミング・頻度) を確認する。

データが毎日決まった時刻に来るのか、随時取れるのかでもワークフローの設計は変わる。

またアプリケーション側と同じKubernetesやオーケストレーション基盤を使う場合、統合の利便性と密結合のリスクを比較する。

  • ソフトウェアエンジニアリング

ソースアクセス用コードを書く場合は、 Networking / Auth / Access Pattern / Retry / Timeout / Pagination / 並列性 / デプロイ を考える。

APIならPagination(全データを一回で取り切れないかも)やレートリミット、DBならDriver Compatibility(ドライバーの互換性)、並列アクセスならソースシステムへの負荷にも注意する。

またCredentialはCodeに埋め込まず、安全に管理する。

これで5章は終わり。

9/14

一般的に夏休みの8,9月の間はなんだかんだ忙しくて、一つ短期のインターンが終わったからようやくオライリーを読んでみたりとかできる時間ができた。だからいまここにまとめを書き上げてみたりしている。

とりあえず今読んでるデータエンジニアリング本は読み切ろうとは思っている。結構手を付けたのに、途中で飽きちゃうこともあるから気をつけないと。

なんか大学入ってから今年が一番予定が埋まっている気がする。今年がここ数年で一番人間らしい営みをしている、とある種言えるかもしれない。

今はようやく2週間程度、予定が全部埋まっている状態ではない状態で過ごせそうだが、逆に何をすればいいのかと焦っているような気持ちもある。本当は好きな事に取り組める時間を手に入れたけれど、時間制限があるし、来月以降に起こることを考えて憂鬱になっている気もする。けれど、一方で、何かしらに取り組んでいないからこそ考える余裕があり、ここまで思考を回して憂鬱を感じているとも言える。そう考えれば、時間が余っていれば幸せとも限らないとも言える。よく分からないものだ。

9/14 Fundamentals of Data Engineering 4章まとめ

第4章を読み進める。テーマはアーキテクチャの選定方法。

まず、選ぶ上で、次のようなポイントがある。

  • Architecture first, Technology second

アーキテクチャは 戦略(what / why / when)、TechnologyやToolはそれを実現する 手段(how)。 先に「Snowflakeを使いたい」「この新しいToolを使いたい」と決めるのではなく、まずビジネス要件に合うアーキテクチャを設計し、その後に技術を選ぶ。 Shiny Object SyndromeやResume-driven Developmentを避けることが重要。

  • チームの大きさ / 能力に合わせて技術選定を行う

チームが小さいほど、複雑なシステムを自前運用する余裕は少ない。巨大テック企業の複雑なアーキテクチャをそのまま真似する Cargo-cult Engineering(必要ないものを儀式的に行なってしまう) は危険。 特に小規模チームでは、マネージドやSaaSを積極的に使い、本当にビジネス上の価値を生む部分にエンジニアの時間を使うべき。 また、PythonやJavaなど、現在のチームの技術に合った選択も重要。

  • Speed to Marketを重視する

技術選定の目的は完璧なシステムを作ることではなく、安全性・品質を保ちながら素早く価値を届けること。 「Launch → Learn → Iterate」のフィードバックループを高速に回す。 何カ月も技術選定だけで悩むより、既に知っているツールを活用し、早く小さな価値を届けることが重要。

  • Interoperability(相互運用性)

データプラットフォームは普通、1つのToolだけでは完結しないため、他のSystemと簡単につながるかが重要。 JDBC / ODBCのようなStandardや、既存コネクタ・APIインテクレーションが充実している技術ほど導入しやすい。 また、将来Toolを交換できるよう、Modularで疎結合な構成を意識する。

  • コストは単純な利用料金だけではない

技術選定ではビジネス価値に対するROIを見る。その際、主に TCO / TOCO / FinOps の3つで考える。

TCO(Total Cost of Ownership)

ツールの料金だけでなく、人件費・インフラ・運用・訓練などを含めた総コスト。 コストにはDirect CostとIndirect Costがあり、購入方法としては CapEx = 最初に大きく投資 OpEx = 利用量に応じて継続的に支払う がある。 CloudのPay-as-you-goはOpEx型で、初期投資が小さく、スケーリングや技術変更もしやすいため、この本ではOpEx-firstを推している。

TOCO(Total Opportunity Cost of Ownership)

技術を1つ選ぶことで、他の選択肢を捨てることによって生じる機会損失。 例えばStack Aを採用すると、そのスキル習得・運用・パイプライン構築に投資するため、簡単にはStack Bへ移れなくなる。

そのため技術選定では、 「今良いか」だけでなく「将来どれくらい簡単に捨てられるか・交換できるか」 も考える必要がある。

FinOps

クラウドのコストを単に削減する活動ではなく、クラウドへの支出から最大のビジネス価値を得るための運用。 コストを継続的に監視し、業務量に応じて資源をスケールアップ/スケールダウンする。 「安くする」こと自体が目的ではなく、必要ならクラウドコストを増やしてでも、Revenue・開発速度・顧客成長などの価値を増やすことが目的。

「将来を見据えた技術選定」と「どこで動かすか」
  • Immutable Technology と Transitory Technology

技術には、長く残りやすい Immutable(不変) なものと、流行して消えやすい Transitory(一時的) なものがある。 例として、Object Storage、Networking、Server、Security、SQL、bashなどは比較的Immutable。 一方、新しいフレームワークやツールはTransitoryになりやすい。

重要なのは、長く残る基盤の上に、入れ替えやすいツールを載せること。

  • 今の要件を優先しつつ、将来の変更に備える

「将来必要になるかもしれない」だけで複雑なアーキテクチャを作ると、過剰なエンジニアリングになりやすい。 そのため、今〜近い将来に最適なテクノロジーを選びつつ、将来交換しやすい構成にする。 本文では、おおよそ2年ごとにテクノロジーを再評価することも勧めている。

特に、 「このツールをやめたくなったとき、簡単に抜けられるか?」 を考え、一つのツールを外せなくなる状態を避ける。

  • オンプレミスとクラウド

オンプレミスはハードウェアを自社で所有・運用する。ハードウェア障害対応、アップグレード、ピーク時のキャパシティの準備まで自分たちで管理する必要がある。

クラウドではハードウェアやマネージドサービスを必要な分だけ借りる。資源を素早く増減できるため、実験やスケーリングがしやすい。

クラウドではさらに、 IaaS → PaaS → SaaS と抽象度が上がる。

IaaSはVMなど、PaaSはRDSやKinesisなどのマネージドサービス、SaaSはSalesforceやFivetranのようにほぼ完成したSoftwareを利用する形。

  • サーバーレス

サーバーを意識せず、業務量に応じて自動でスケールする仕組み。 Scale to Zero(使ってなければスケールをゼロにできる) → 大量処理まで自動スケーリング + Pay-as-you-go が特徴。

「サーバーが存在しない」のではなく、サーバー運用を利用者から隠していると考える方が正確。

  • クラウドはオンプレミスの置き換えではない

オンプレのサーバーをそのままクラウドVMへ移す リフト&シフト は移行の第一歩としてはよいが、そのまま使い続けると高コストになりやすい。

クラウドの価値は、 オートスケーリング / スポット / リザーブドインスタンス / サーバーレス などクラウド特有の価格モデルを活用することで初めて出る。

つまり、 クラウドに設計し直すことが重要。

  • クラウドのコストは資源だけで決まらない

クラウド供給者はCPUやストレージ容量だけでなく、 耐久性 / 信頼性 / 予測可能性 / 割り込み力 なども価格に反映している。

例えばアーカイブストレージは保存は非常に安いが、取り出すと高い。スポットインスタンスは安い代わりに途中で止められる可能性がある。

そのため、単純な「1CPUいくら」ではなく、作業の性質と価格モデルを合わせることが重要。

  • Data Gravity と Egress Cost(データ取り出し料金)

クラウドでは、データを入れるのは安くても、クラウド外へ出すData Egressが高いことが多い。

大量のデータを置くほど、そのプラットフォームから移行しにくくなる。これを Data Gravity と呼ぶ。

したがってクラウド選定では、単純な利用料金だけでなく、将来データを移動するときのコストやLock-in(特定の製品に依存してしまう状態)も考える必要がある。

  • ハイブリッドクラウド

オンプレとクラウドを併用する構成。

例えば、 アプリケーションはオンプレのまま、分析だけクラウドに移すことができる。

特にDataをオンプレ → クラウドへ送ってクラウド内で分析する構成は、Data Egressを減らしやすい。

  • マルチクラウド

AWS / Azure / GCPなど複数クラウドを併用すること。

メリットは、各クラウドのベストサービスを選べたり、顧客の近くで処理できること。

一方で、 Networking / Security / Integration / Egress Cost / Operational Complexity が大きく増える。

そのため、明確な理由がなければシングルのクラウド利用の方がシンプルでよい。

  • Cloud Repatriationは特殊ケース

DropboxやCloudflareのようにクラウドからオンプレへ戻した事例があるが、これは一般企業にそのまま当てはまらない。

これらは、 Exabyte級Storage / Tbps級Traffic / 非常に高いEgress Cost を持つ特殊な企業。

つまり、 「DropboxがOn-premに戻した → クラウドは高いから自社も戻す」 という判断は決定性に欠ける。

通常の企業では、クラウドの柔軟性・マネージドサービスのメリットの方が大きいことが多い。

ビルドするか、購入するか

Build vs Buyの基本

Buildは自由度と製品の制御性が高い一方、開発・運用・保守に大きなリソースが必要。 BuyはVendorやOSS(オープンソースソフトウェア)に依存するが、既存の成熟した仕組みを使える。

基本方針は、 「自社の競合へのアドバンテージになる部分だけBuildし、それ以外は既存のものを使う」 という考え方。

判断はTCO・TOCO・Competitive Advantageで行う

単に「作れるか」ではなく、 TCO(総コスト) TOCO(他の選択肢を失うOpportunity Cost) その仕組みが自社の強みになるか で考える。

例えば普通のRDBMSで十分なのに自社DBをゼロから作るのは、ほとんどの場合ROIが悪い。

  • OSSを選ぶときのポイント

OSSは無料でも、運用コストは無料ではない。 特に見るべきなのは、 Mindshare(OSSがどれくらい知られていて、使われているか) / Maturity(そのOSSがどれくらい成熟しているか) / Community(助け合える利用者・開発者コミュニティがあるか) / Troubleshooting(障害やBugが起きたときに、問題を特定して解決しやすいか) / Roadmap(今後そのOSSがどこに向かって開発されるのかが見えるか) / Maintenance負荷(導入後に自分たちがどれくらい面倒を見る必要があるか) など。

人気があり、活発に開発されていて、Production実績があるプロジェクトほど安心して採用しやすい。

  • Community OSS と Commercial OSS(COSS)

Community OSSでは、自分たちでホスティング・アップグレード・バグ対応などを行う。

COSSでは、OSSをベンダーがマネージドサービスとして提供する。 例として Databricks、Confluent、dbt Labs など。

COSSを選ぶときは、 マネージド化による価値 / サポートの手厚さ / リリースの状態 / 価格体系 / ベンダーの経営安定性 を見る。

要するに、 「自分たちでOSSを運用するコスト」と「ベンダーに払う料金」を比較する。

  • Proprietary Product(特定の企業が独自開発)を選ぶとき

クローズドソースな製品でも、マネージドサービスとして非常に優秀なものは多い。

特に確認するのは、 相互運用性 / 市場のシェア / ドキュメントの豊富さ / サポートの手厚さ / 価格面 / 制作会社の状態 など。

安く見えても、他ツールとの接続が悪かったり、ベンダーが消えたり、長期契約でLock-inされると大きな問題になる。

  • Cloud Vendor独自Service

DynamoDBのように、AWS / GCP / Azureが独自に提供するマネージドサービスもある。

Cloud内で強く統合されていて便利だが、Vendor Lock-inが強くなりやすい。 そのためパフォーマンスだけでなく、価格・TCO(Total Cost of Ownership)・長期契約・移行しやすさも考える。

・マネージドサービスを使う価値

データエンジニアの時間を、サーバー管理やアップグレードなどの無駄な労働に使うのではなく、 ビジネス価値を生むデータプロダクトやプラットフォーム開発に使える。

つまり「自前運用できるからやる」のではなく、その運用を自分たちがやる価値があるかを考える。

モノリスとモジュール性のTrade-off
  • モノリス

多くの機能を1つのシステムにまとめる構成。 メリットは、構成が単純で理解しやすく、使用技術も依存性も少ないため、初期開発や運用が楽なこと。

一方で、コンポーネント同士が強く結合するため、 一部の障害が全体に波及する / リリースが重くなる / リソース競合が起きる / 別システムへの移行が難しいといった問題がある。

特にデータパイプライン全体が1つにまとまっていると、途中で1箇所壊れただけで全処理をやり直すようなことも起こる。

  • モジュール性

システムを役割ごとの小さなコンポーネントに分け、APIや標準フォーマットを通じて疎結合に接続する考え方。

各コンポーネントを独立して変更・交換できるため、 用途ごとにBest-of-breed Tool(業務や目的ごとに最も優れた技術)を選べる / 使用技術を交換しやすい / 各チームが独立して開発できる というメリットがある。

データでは、例えばObject StorageにParquetで保存しておけば、Sparkでも別のProcessing Engineでも読める、という形がモジュール性につながる。

  • Modularityの弱点

コンポーネントを分ければ分けるほど、管理するシステム数・統合必要性・運用の複雑さが増す。

そこで重要になるのがオーケストレーション。複数ツールの実行順序や依存関係を管理し、モジュールなデータスタックをつなぐ接着剤の役割を持つ。

  • Polyglot / Swappable Components(可換コンポーネント)

モジュール化されたシステムでは、利用者は内部実装ではなくインターフェースだけを意識すればよい。 例えばPythonで書かれたサービスをJava版に置き換えても、API仕様が同じなら他システムは変更しなくてよい。

つまり、内部の技術を変更しても外部への影響を小さくできる。

  • 分散モノリス

見た目は分散システムなのに、実際には共通コードベースなどに強く依存している状態。

例えばクラスター内の全Jobが同じLibrary Versionを共有すると、一つの依存したモジュールのアップグレードが他のJobを壊す可能性がある。

Airflowでも、全Workerに同じPython Dependencyを入れる構成では、DAGごとのLibraryが衝突することがある。

つまり、 「サーバーを分けた = モジュール化できている」ではない という重要な点。

分散モノリスへの対策

代表的なのは、

Ephemeral Infrastructure → Jobごとに一時的なクラスターやサーバーを作る

Container → Jobごとに依存関係や実行環境を分離する

ことで、依存関係の矛盾を減らす。

サーバーレスのサーバーの違う点

サーバーレスとは

サーバーを自分で管理せず、必要なときだけ処理を実行する仕組み。代表例は AWS Lambda や BigQuery。

特徴は、 インフラ管理が少ない / 自動スケーリング / Pay-as-you-go / Scale to Zero。

特に小さく独立した処理では、素早く導入でき、Time to Valueが高い。

サーバーレスは常に安いわけではない

実行回数が少なければ非常に安いが、高頻度で大量のイベントを処理すると、通常のサーバーより高くなる場合がある。

そのため、コスト対イベントを監視 → 将来のイベント数をモデル化して費用を予測することが重要。

BotやDDoSで大量Requestが来た最悪ケースも考える必要がある。

  • コンテナ

コンテナはアプリと依存環境を隔離して実行する仕組み。VMと違ってOS全体を持たないため、比較的軽量。

主な利点は、 独立な依存関係 / 移植性 / リソース分離。

以前出てきた分散モノリスの依存関係競合を減らす方法としても有効。

Kubernetesは多数のコンテナを管理・スケールするための仕組み。

コンテナとサーバーレスの境界は曖昧

サーバーレスの裏側でもコンテナが使われることが多い。

AWS Fargateのように、 コンテナは使うがサーバーやクラスタは管理しない サービスもある。

つまり、 サーバー → コンテナ → マネージドコンテナ / サーバーレス と、インフラの抽象度が上がっていくイメージ。

サーバーを使うべき場合

サーバーレスより、 長時間処理 / 高頻度処理 / 大量CPU・メモリ / 複雑な依存関係 / OSレベルの自由度 が必要ならサーバーやコンテナの方が向いている。

また一定以上の継続的作業では、サーバーを常時動かした方が安くなる場合もある。

  • サーバーを使う場合もCloud Native(最初からクラウド上で動作することを前提として設計・開発されたシステムやアプリケーション、またソフトウェアアプローチ)にする

サーバーを「壊れない特別な1台」として管理するのではなく、いつ壊れても作り直せるEphemeral Resourceとして扱う。

そのため、 CI/CD / Image・Boot Script / Autoscaling / Cluster / Infrastructure as Code を使う。

TerraformやCloudFormationなどでインフラ自体も再現可能にする。

サーバーレスにするかの判断基準

主に見るのは、 Workload Size / Complexity(その処理がどれくらい重い・複雑か) Execution Frequency / Duration(どのくらいの頻度で実行されるか、1回あたりどのくらい時間がかかるか) Networking Requirements(その処理がどんなNetwork接続を必要とするか) Language(使用したいProgramming Languageが、そのServerless Platformで正式に対応されているか) Runtime Limitations(Providerが用意した実行環境の制約の中で動かす必要がある) Cost(Serverlessは使った分だけ払うので、低頻度ならかなり安い)

つまり「サーバーレスで動くか」だけでなく、制限内で自然に動かせるWorkloadかを見る。

データマネジメントの観点

技術を選ぶときは、機能だけでなく セキュリティー / プライバシー / コンプライアンス / データの質 / ガバナンス をどう扱っているかを見る。

特にマネージドサービスでは内部実装が見えにくいので、 「GDPRやCCPAに対応しているか」「データをどこに置けるか」「品質をどう保証するか」などをVendorに確認する必要がある。

OSSでも同様に、これらを自分たちでどう担保するか考える。

DataOpsの観点

障害は必ず起きる前提で、 デプロイ / 監視 / アラート / エラー発生時の応答 をどう実現できるか確認する。

OSSなら自分たちで監視や運用を用意する必要があることが多い。

マネージドサービスならVendor側に任せられる部分が多いが、 SLA / 障害通知 / 対応状況の透明性 を確認する必要がある。

データアーキテクチャの観点

技術選定でも重要なのは、 Trade-off / 可逆性 / 相互運用性 / ROI。

今の「Best Tool」が将来もBestとは限らないので、 Lock-inを避け、交換しやすく、他ツールと接続しやすい技術 を選ぶ。

Airflowの例

Airflowの強みは、 大きなMindshare / 活発なCommunity / 多数のマネージドサービス / OSSとしての成熟度 にある。

一方で、 スケジューラやBackend DBがボトルネックになりやすい / 分散モノリス的 / スキーマ・カタログ・リネージュなどData-native機能が弱い / 開発・テストが難しい という弱点もある。

PrefectやDagsterなどは、こうしたAirflowの弱点を改善しようとしている。

Software Engineeringの観点

データエンジニアは、できるだけ単純かつ抽象化した状態を目指すべき。

既に解決済みの一般的な問題はOSSやマネージドサービスを使い、自社の競合に対するビジネスアドバンテージにならない部分を自作しない。

例えば「DB → Cloud DWHのコネクタ」を自作するより既存ツールを使い、自社独自のアルゴリズムやビジネスロジックにエンジニアの時間を使う方が価値が高い。

これで終わり。ここまでは細かい部分じゃなかったから、さらに細かい部分を明日以降読んでまとめる。

9/13~14

第3章 良いデータアーキテクチャのデザイン方法を読み進める

データアーキテクチャについて

Enterprise Architectureとは:組織全体の変化に対応するために、柔軟で可逆的な意思決定を行い、Trade-offを評価しながらシステムを設計すること。技術そのものが目的ではなく、Business Goalを実現するための設計であることが重要。

Reversible Decision(可逆的な意思決定) 将来を完全に予測することはできないため、できるだけ後から変更・撤回しやすい設計にする。 具体的には、One-way Door = 戻りにくい決定、 Two-way Door = 容易に戻せる決定 という考え方で、できるだけTwo-way Doorとして設計することで、素早く試行錯誤できる。

Change Managementと小さな変更 大規模なArchitecture変更も、一度に全部変えるのではなく、小さく具体的で、できれば可逆的な変更に分割して進める。 Architectureは将来像を描くだけでなく、現在の問題から目標状態までを段階的に実現するもの。

Trade-offは避けられない Architectureに「絶対に正しい設計」はない。 コスト、レイテンシ(入力から出力までの時間)、信頼性、煩雑さ、スケーラビリティなどの制約があるため、メリットとデメリットを比較して最も適切な選択をする必要がある。 そのため「Best Architecture」ではなく、現実の条件でのLeast Worst Architectureを目指す。

データアーキテクチャとは データアーキテクチャとは、Enterprise Architectureの考え方をデータに適用したもので、変化し続ける企業のData Needsを支えるために、柔軟かつ可逆的な意思決定とTrade-off評価によってData Systemを設計すること。 データエンジニアリングアーキテクチャはその一部で、データソース / データ取り込み / ストレージ / データ変換 / データ提供などの仕組みを設計する。

Operational Architecture と Technical Architecture Operational Architecture = What → 何を実現する必要があるか。Business Process、Data Quality、必要なLatencyなど。 Technical Architecture = How → それを技術的にどう実現するか。Ingestion、Storage、Transformation、Servingの具体的な仕組みなど。 つまり、まずBusiness Requirementを定義し、それをTechnical Designへ落とし込む。

良いデータアーキテクチャの条件 良いアーキテクチャは、ビジネス要件を満たしながら、共通で再利用できる基礎的な構成要素(Building Block)を使い、柔軟で変更しやすい。 逆に、Tightly Coupled(密結合、2つ以上のものが複雑に絡み合う)、Rigid(融通が効かない)、Overly Centralized(一極集中型)、One-size-fits-all(1つの方法でゴリ押し、柔軟性なし)な設計は変更を難しくする。

アーキテクチャは完成しない データアーキテクチャは一度作って終わりではない。ビジネスの状況、技術の環境、ユースケースが変化するため、継続的に進化させる生きたシステムとして考える必要がある。

いいデータアーキテクチャの9つの原則
  1. 共通のコンポーネントを賢く選ぶ

組織全体で使える共通部品を選ぶことが重要。例として、Object Storage、Version Control、Observability、Monitoring、Orchestration、Processing Engineなど。 共通化すると、チーム間の連携や再利用がしやすくなる一方で、One-size-fits-allを強制して各チームの生産性を落としてはいけない。共通化と柔軟性のバランスが必要。

  1. Failureを前提に設計する 「壊れないシステム」ではなく、壊れても耐えられるシステムを作る。特に重要なのが次の4つ。 Availability(可用性):利用可能な時間の割合 Reliability(信用性):期待された動作を満たせる確率 RTO(Recovery Time Objective):障害から復旧するまでに許容できる最大時間 RPO(Recovery Point Objective):障害時に許容できる最大データ損失 壊れた場合のビジネス的なインパクトに応じて、どの程度の可用性・復旧能力が必要かを決める。

  2. スケーラビリティと柔軟性(Elasticity)を設計する 負荷が増えたら スケールアップ(質を上げる) / スケールアウト(数を増やす)できるだけでなく、負荷が減ったら スケールダウンできることも重要。 動的に増減できるシステムを Elastic といい、さらに未使用時に完全停止する Scale to Zero もある。 ただし、必要以上に複雑な分散構成を作るとコストと運用負荷が増えるため、実際の負荷に応じた適切なScaling Strategyを選ぶ。

4.アーキテクチャはリーダーシップでもある アーキテクトの役割は技術を一人で決めることではなく、技術的な方向性を示し、チームを教育・支援し、組織全体の能力を高めること。 Command-and-Controlで「全員このDBを使え」と強制するのではなく、Data Engineerと相談しながら適切な技術選択を行う。 良いArchitectは、自分がボトルネックになるのではなく、他のEngineerがより高度な問題を解けるよう育てる。

  1. Always Be Architecting アーキテクチャは一度作って終わりではない。 Baseline Architecture(現在)→ Target Architecture(目標)→ Sequencing Plan(どう移行するか) を常に更新する。ビジネスの状況や技術が変化するため、Target Architecture自体も固定ではなく動き続ける。

6.疎結合システムを作る システムを小さなコンポーネントに分割し、APIやメッセージなどの明確なInterfaceを通じて通信する。内部実装を隠すことで、あるコンポーネントを変更しても他のコンポーネントへの影響を最小化できる。 これは組織にも当てはまり、各Teamが担当コンポーネントを独立して開発・Deployできるようになる。 つまり、疎結合システム → Teamの独立性・開発速度向上につながる。

  1. 決定は可逆的な方向でする データテクノロジーは非常に速く変化するため、将来変更できない設計は避ける。 可能な限り Two-way Door(後から戻せる意思決定) にし、技術を交換・Upgradeしやすくする。 疎結合やモジュール化は、この可逆を実現するためにも重要。

  2. セキュリティを最優先する 特に重要なのが ゼロトラスト と 責任共有モデル。 ゼロトラストでは「社内ネットワークだから安全」と考えず、内部・外部を問わずアクセスを信用せず検証する。 クラウドでは、クラウドプロバイダーが基盤を守る Security of the Cloud と、利用者が自分のData・IAM・設定を守る Security in the Cloud に責任が分かれる。 そのため、データエンジニア自身もセキュリティエンジニアとして責任を持つ必要がある。

  3. FinOps(finance * devops)を取り入れる CloudではPay-as-you-go(従量課金)なので、性能だけでなくCostもArchitectureの一部として継続的に管理する。 例えば、スケールアップ/ダウン、Spot Instance(余剰リソースの貸し出し)、Pay-per-query(クエリ課金) vs Reserved Capacity(予備力)などをCostとPerformanceの両面から判断する。 またコストを監視し、異常な支出に警告を出すことも重要。大量ダウンロードなどでクラウド費用を意図せず急増させるコスト面での攻撃 も考慮する。

アーキテクチャの主要な設計概念
  • ドメインとサービス

ドメインは「売上、会計、在庫」のような現実世界の業務領域、サービスはそのドメイン内で特定の仕事を担当する機能。 例えばセールスドメインの中に 注文 / 請求書 / 製品 がある。サービスは複数ドメインから共有されることもある。 重要なのは、他社の構成をそのまま真似せず、実際のユーザーに話を聞いてドメインとサービスを設計すること。

  • 分散システム・スケーラビリティ・システム不良(failure) データシステムでは主に、 スケーラビリティ / 柔軟性 / 可用性 / 信頼性 を考える。

1台を強くする垂直なスケーリングには限界があるため、大規模システムでは複数マシンを使う 水平スケーリング(スケールアウト) / 分散システムが重要になる。 分散システムではデータレプリケーションやフェイルオーバー(予備の機器に動作を切り替えれる措置)を使って、システムの一部が壊れても処理を継続できるようにする。

  • 密結合と 疎結合

密結合はコンポーネント同士の依存が強く、一部の変更が全体へ影響しやすい。 疎結合は独立性が高く、各コンポーネントやチームが個別に変更・デプロイしやすい。 ただし疎結合を進めすぎると、各チームが独自仕様を作り、データが互いに使えなくなる可能性もあるため、標準・責任の所有は共通化する必要がある。

Single-tier と Multitier Architecture

Single-tier はApplicationとDatabaseなどを1つのServerにまとめる構成。Simpleだが、1か所の障害で全体が止まり、Resource競合も起こるためProductionには向きにくい。

Multitier は、 Data / Application Logic / Presentation などを分離する。 各Layerを独立させることで、Reliability・Scalability・Technology選択の自由度が高まる。

基本は 最初はSimpleにし、必要に応じてLayerを分離する。

Monolith と Microservices

Monolith は多くの機能・Domainを強く結合したArchitecture。Simpleに始められる反面、規模が大きくなると変更やComponent再利用が難しくなり、最悪の場合 Big Ball of Mud になる。

Microservices は特定の機能を持つ独立したServiceに分割し、Loose Couplingにする考え方。あるServiceが停止しても他Serviceが動作し続けられる。

ただし Microservicesが常に正解ではない。最初はMonolithで素早く作り、成長に応じてServiceを切り出すのも合理的。

Data Architectureでは「Loose Couplingを理想」とする

Softwareと違い、Dataでは中央Data WarehouseのようなMonolithicな構成も多い。 そのため「必ずMicroservicesにする」のではなく、

可能な範囲でModular・Loosely Coupled・Reversibleにする

という現実的な考え方が推奨される。

Domainの分離についても、中央Data Teamが全部管理するCentralized方式と、各Domain Teamが自分たちのData Productを管理する Data Mesh のような方式がある。

シングルテナントとマルチテナント

複数のチームや顧客で同じデータシステムを共有するかを考える。

マルチテナントで特に重要なのは、パフォーマンスとセキュリティ。

あるテナントの大量利用で他テナントが遅くなるノイジーネイバー問題や、顧客間でデータが漏れる問題を防ぐ必要がある。

  • イベント駆動型アーキテクチャ

注文作成や顧客更新など、「何かが起きた」というイベントを中心にシステムを連携させるアーキテクチャ。

基本は、 イベント発生 → ルーチン → データ という流れ。

データ生成者とデータ利用者を直接結びつけずEventを介することで、疎結合になり、複数利用者が同じイベントを利用したり、一部サービスが停止しても処理を継続しやすくなる。

Brownfield と Greenfield

Brownfield は既存アーキテクチャを改善するProject。古いレガシーなシステムとの互換性や移行が必要なので難しい。 全て破壊して全部作り直すより、既存システムを少しずつ新しステムに置き換える Strangler Pattern が推奨される。

Greenfield は完全に新しく作るプロジェクト。自由度は高いが、「新しいツールを使いたいだけ」の Shiny Object Syndrome / Resume-Driven Development に注意する。

どちらでも重要なのは、 必要な目的を優先し、トレードオフである事を考え、可逆的な決定とROIを重視すること。

データアーキテクチャの例、内部
  • データウェアハウス

レポートや分析のための中央集約型の分析基盤。 OLTP(オンライントランザクション処理)の本番DBから分析処理を分離し、ETL/ELTでデータを整理して蓄積する。 特にクラウドデータウェアハウスでは、の分離・Pay-as-you-go・大規模並列処理により、以前より安価かつ柔軟に使えるようになった。 部門別に最適化したサブセットがデータマート。

  • ETLとELT

ETL:Extract → Transform → Load DWHに入れる前に外部で変換する。 ELT:Extract → Load → Transform まず生データをDWHに入れ、SnowflakeやBigQueryなどの強い計算能力を使って後から変換する。 Cloud DWHの普及でELTが一般的になっている。

  • データレイク

Structured / Semi-structured / Unstructuredを問わず、大量の生データをObject Storageなどに低コストで保存するアーキテクチャ。 Compute(SQLを実行するCPU/メモリ)とStorage(データを保存するディスク)を分離し、SparkやPrestoなど好きなエンジンで処理できる自由度が強み。 一方、初期のデータレイク1.0はスキーマ、カタログ、データの発見可能性、Update/Deleteなどのデータマネジメントが弱く、 Data Swamp / Dark Data / WORN(Write Once, Read Never) になりやすかった。

  • データレイクハウス/データプラットフォーム

Data Lakeの柔軟性と、Data WarehouseのSchema管理・ACID・Data Management・高性能SQLを融合しようとするArchitecture。 現在はDWH側もObject StorageやSemi-structured Dataを扱い、データレイク側もACIDやメタデータ管理を持つようになっており、ウェアハウスとデータレイクの境界が曖昧になっている。

Databricks、Snowflake、AWS、Azure、Google Cloudなどは、より広い Data Platform へ進化している。

  • モダンデータスタック

昔の巨大なモノシリックなツールではなく、 Cloud-based / Plug-and-play / Modular な製品を組み合わせてデータプラットフォームを構築する考え方。 Pipeline、Storage、Transformation、Governance、Monitoring、BIなどを専用Toolとして組み合わせる。 目的は複雑さを減らし、Self-service・Agility・Modularityを高めること。

  • Lambda / Kappa / Unified Batch & Streaming

Lambdaアーキテクチャは、 バッチレイヤー + ストリーミングレイヤー + データ提供レイヤー を別々に持ち、低Latencyと正確なBatch処理を両立しようとしたもの。 ただし、同じ処理を複数コードベースで管理する複雑さが大きい。 Kappaアーキテクチャは、ストリーミングシステムだけを中心にして、必要なら過去イベントを再実行してバッチも処理する考え方。ただしストリーミング基盤だけですべてを処理するのは複雑・高コストになりやすい。 現在はApache Beam / Dataflow / Flink / Sparkなどで、 「バッチは有限なストリーミングの特殊ケース」 として同じコードでバッチとストリーミングを扱う方向が進んでいる。

  • IoTアーキテクチャ

IoTでは、 デバイス → Gateway → 取り込み → 保存 → 変換 / 提供 という流れが基本。 Deviceはセンサーなどから継続的にデータを生成し、必要ならエッジコンピューティング(利用者や端末(エッジ)の物理的に近い場所でデータ処理を行う) / Edge MLも行う。 IoT特有の課題として、 通信断・到着が遅延するデータ・スキーマのばらつき・低Bandwidth(低い通信速度)・データ汚染 などを考慮する必要がある。 データの保存方法や提供方法はレイテンシの要件によって変わり、Batch Object Storage、Message Queue、時系列DB、ストリーミング処理などを使い分ける。

  • データメッシュ

巨大な中央集約型データプラットフォームへの反省から生まれた考え方で、データの所有者を各ビジネスドメインへ分散する。 4つの柱は、 Domain-oriented decentralized ownership・・・データの所有・管理責任を、中央Data Teamではなくその業務を一番よく理解しているDomain Teamに持たせること

Data as a Product・・・利用者が安心して使えるように、意味が明確・品質が高い・Discoverable・信頼できる・使いやすい状態にする

Self-service Data Platform・・・中央のPlatform Teamが、各Domainが自分たちでData Productを簡単に作れる共通基盤を提供

Federated Governance・・・全社共通ルールとDomainごとの自主性を組み合わせる

セールスなど各領域のチームが、自分たちのデータを他チームが使えるデータ製品として提供する。

  • アーキテクチャを選ぶ基本姿勢

どのアーキテクチャにも絶対的な正解はない。 新しい流行に飛びついたり、特定アーキテクチャに固執するのではなく、ビジネス要件・コスト・煩雑性・スケーラビリティ・運用性を見ながらトレードオフで選ぶことが重要。

結論:良いData Architectureに絶対的な正解はなく、組織固有のBusiness Requirementに合わせてTrade-offを評価しながら設計することが重要

これで3章が終わり。

9/12~13

Fundamentals of Data Engineeringの続き

データエンジニアの経歴とスキル

  • データエンジニアリングは新しい分野だから体系的に学ぶ大学とか手段はあんまりない、だから共通のカリキュラムがない

  • ソフトウェアエンジニアリング、ETL開発、データベース管理、データサイエンス、データ分析などをやってた人はデータエンジニアリングと共通する部分があるからなりやすいよ

事業上の責任

  • 非技術者とのコミュニケーション、組織内の人間関係を知っておくことも大事

誰がこのデータを使いたいのか、どんな意図かを深く洞察するには必要だよねという話。耳が痛い。

  • 何を作るべきかを把握した上で、それに関係する人から同意を取ること

  • コスト管理、devops、dataops、アジャイルの考え方を、技術的に解決することだけでなく、組織的に考え方を浸透させること

データを使う人たちとコミュニケーションをとり、ステークホルダーとの連携が大事

技術的な責任

データエンジニアリングの主要な要素は、安全性、データ管理、データ操作、データのアーキテクチャ、オーケストレーション、ソフトウェアエンジニアリング

  • データエンジニアはコードをかけるべき。なぜなら、エンジニアは現在オープンソースやSaaSを使うことが多いから、データエンジニアは現在、高レベルの抽象化や、オーケストレーションフレームワーク内でパイプラインをコードとして記述することに重点を置いている。つまり、この橋渡し部分をかけないといけないという話。つまり、ソフトウェアエンジニアでもあると言える。

よく使うのはSQL,Python,Java,Scala,bashなどらしい。

  • SQL → 言わずもがな。分析クエリとかで書くし、データマートとかもこれで書いたりするよね

  • Python →基盤となるコンポーネント間の接着剤のような役割。Airflowってやつもそうらしい。Airflowは自分は名前しか知らない

  • JavaやScalaなどのJVM言語 → 一般的なSpark、Hive、DruidなどのApacheオープンソースプロジェクトの場合、JVMは一般的にPythonよりもパフォーマンスが高く、Python APIよりも低レベルの機能にアクセスできる場合があるらしい。まだ使ったことないかも

  • bash → 要するにshell。ある程度わかると便利だけど、AIに書かせることもできる気もする。ここは記事がちょっと古いかも?

技術の変化が激しいから、結局普遍的な思考の部分を身につけてねという思想はここもそう。

データエンジニアリングの役割の連続性(AからBまで)

データエンジニアは2種類の人がいるよという話。

  • A型エンジニア(abstruct)は、主に既製の製品、マネージドサービス、ツールのみを使用してデータエンジニアリングのライフサイクルを管理する人。データアーキテクチャをできるだけ抽象的で分かりやすく保つのが役割で、車輪の再発明はしない。基礎的。

  • B型エンジニア(building)は、ステージ2,3などの企業でよくみられる、企業のコアコンピタンスと競争優位性を活用し、拡張性のあるデータツールとシステムを構築する人。つまり、メンテナンス要員ではなく、最新技術を使って基盤を改造したりする人。応用的。

組織内のデータエンジニア
  • まず、社内向けデータエンジニアと社外向けデータエンジニアがいるよねという話

社外向けデータエンジニアは、社外の人がアプリを使ったトランザクションデータとイベントデータを収集、保存、処理するシステムを設計、構築、管理して、またアプリにフィードバックしたりするのが仕事。難点は、外部向けクエリエンジンは、内部向けシステムよりもはるかに大きな同時実行負荷を処理することがよくあること。また、外部からクエリアクセスが来るので、データベースのセキュリティをしっかりしないとダメ。まあこれは日本だとインフラエンジニアとかバックエンドエンジニアがやってるイメージもある?

社内向けデータエンジニアは、BIダッシュボード、レポート、ビジネスプロセス、データサイエンス、機械学習モデルのためのデータパイプラインとデータウェアハウスの作成と維持など。これは、データアナリストやアナリティクスエンジニアなどが日本だと該当する気がする。

  • データエンジニアは、データ生成者(上流)と、データ使用者(下流)の2種類の人と関わる

データ生成者(上流)にはソフトウェアエンジニア、データアーキテクト、DevOpsエンジニア、サイト信頼性エンジニア(SRE)

データ使用者(下流)にはデータアナリスト、データサイエンティスト、機械学習エンジニアなどが該当する

これら各ステークホルダーの詳細を軽く触れる

データアーキテクトは、組織のデータ管理の設計図を作成し、プロセス、全体的なデータアーキテクチャ、システムを設計する人。組織の技術部門と非技術部門の間の橋渡し役もする。要するに、データのアーキテクチャ決めとかする役割だが、データエンジニアがここもやってたりすることもある。

ソフトウェアエンジニアは、ソフトウェアエンジニアビジネスを運営するソフトウェアとシステムを構築する人。要するにSaaSとかでは製品を作る人で、この際にイベントログとかを仕込んでもらい、それを分析できる形にしたい。この際に、ソフトウェア側について詳しいのはSWEだから、データエンジニアはこう言った人にこれってどんなタイミングでイベントログ集計してます?とか聞かないといけないから、連携が必要。

DevOpsエンジニアとサイト信頼性エンジニアもいるが、これもSWEと同様、上流のシステム設計をしてくれているから、詳細をこの人たちに聞いて連携しようという話。

データサイエンティスト・データアナリスト・機械学習エンジニアは下流なので、データエンジニアが作ったデータを利用するわけだが、データが前処理ができていなかったり、崩れていると分析しずらいから効率が悪くなってしまう。だから、分析しやすい基盤を作るべきだし、これらの人と話し合って、どんな分析を普段しているのかを聞き、それをしやすい形にアーキテクチャ、データマートを整えるとかできるといいのかも。

後は、企業のデータ活用の重要度が上がっているから、幹部とかとのやりとりもあるみたいな話。

これで第1章おわり。なんか頑張って書いてたけど実務でなんとなく察することが多いって感じで、もっと他の話を知りたいかもって感じだった

第2章へ

第2章:データエンジニアリングのライフサイクル

データエンジニアリングのライフサイクルという概念について学ぶ

まず、データエンジニアリングは、5つの段階に分けられるよ

データ生成(generate)→データ保存(storage)→取り込み(ingest)→データ変換(transform)→データ提供(serve)

ただし、ライフサイクルの中で、一部工程が逆になったり、混ざったりとかもあるよ

データライフサイクルとデータエンジニアリングライフサイクル

2つの言葉の違いは、データライフサイクルがデータのライフサイクル全体を指すのに対し、データエンジニアリングライフサイクルは、データエンジニアが管理する段階に焦点を当てているものらしい

データ生成部分について

データのソースとなるシステムには、IoTデバイス、アプリケーションメッセージキュー、トランザクションデータベースなどがある。要するに、生DBからデータをとってくる必要がある。

この生データでも、アプリケーションDB = 業務・アプリの「状態」を保存するデータ IoTデータ = 現実世界で発生した「イベント・観測」を継続的に記録するデータ であり、データの性質が違う。

データエンジニアは、これらのデータソースを扱う上で、次のようなことを考えないといけない。

データソースの本質的な特徴はアプリケーションかIoTデバイスの群れのどっち?

ソースシステムではデータはどのように永続化される?データは長期的に永続化されるか、それとも一時的なもの?

データは1秒あたり何件のイベントが発生?1時間あたり何ギガバイト?

出力データにどの程度の整合性を期待できる?想定外のヌル値や不適切なフォーマットなど、データの不整合はどのくらいの頻度で発生する?

エラーはどのくらいの頻度で発生?

データの重複は大丈夫?

一部のデータ値は、同時に生成された他のメッセージよりも大幅に遅れたりすることはない?

取り込まれたデータのスキーマはどのようなもの?複数のテーブル、あるいは複数のシステムを結合する必要はない?

スキーマが変更された場合の対処と、下流への伝達方法は?

ソースシステムからデータを取得する頻度は?

データのプロバイダーは誰?

データソースからの読み込みは、データソースのパフォーマンスに影響を与えますか?

ソースシステムは上流のデータ依存関係を持っている?また、上流のデータの特徴はあ? 遅延データや欠落データをチェックするためのデータ品質チェックは実施されている?

こう言ったことを考える上で難しいのはスキーマの構築。

データエンジニアの重要な仕事の一つは、ソースシステムのスキーマにある生データを入力として受け取り、それを分析に役立つ出力に変換すること。

一応、スキーマレスと呼ばれる、スキーマとちょっとデータが違っても柔軟に格納してくれるものもあるらしい。

ストレージについて

データソース部分と同じぐらい丁寧に書いていたら長くなるので簡潔にここからは書く。

ストレージはもちろん保存場所だけど、拡張性とかが大丈夫か、中身の仕組みと、使用用途に合った状態にできているかが重要。

頻繁にアクセスされるデータは取り出しやすく、あまりアクセスされないデータはアーカイブにといったことが必要。

ポイントとしては、 Storageは単なる保存場所ではなく、基盤全体の設計に影響する データのアクセス頻度によってHot / Warm / Coldを考える 用途によって複数のストレージを使い分けるのが普通

データ取り込みについて

「データをどこから、どのタイミングで、どの方法で取り込むか」を設計する段階

基本的に、Ingestionはデータ基盤の大きなボトルネックになりやすいということに注意。

また、まとめてデータ取り込みをするbatchとstreamingがある。batchがまとめて処理、streamingがリアルタイム処理。基本はstreamingの方が便利に見えても、バッチにしないといけない。(シンプルにstreamingは難しい)

CDC(Change Data Capture)・・・DBの変更だけを取得する仕組み。

データ変換について

取り込んで保存した生データを、分析・レポート・MLで使える形に変える工程

重要なのは、Transformationで初めてデータが「使える価値のある形」になるということ。

Transformationの中には、いくつかの工程が含まれていて、

まず、基本的なクリーニング(正規化,非正規化,JOIN,schema変更)など

加えて、MLを使うなら、特徴量作成をするのもTransformationだし、Transformationは、実はビジネスルールをデータに埋め込む工程であることが重要。

個数と値段のデータがあったら、掛け合わせて売上列を作るみたいな、新しい必要になる情報を加工して足しておくことも必要な時がある。ちなみに、dbtはsqlでtransformationを記述できるのが便利。

このtransformation自体は、データレイク→データウェアハウス→データマートの変換のどこでも起きる。

Transformationを設計するときの主な問いは、 この変換にどんなビジネス価値があるか コストに対してROIはあるか 処理をできるだけ単純・独立にできないか どのビジネスルールを実装しているのか など。 また、Transformationを複雑な巨大SQL一発で作るより、小さい変換に分ける、という考え方も重要。

データ提供について

最後に、ユーザーやアナリストなどにデータ提供する段階について。

この段階で一番注意すべきなのは、使われないデータには価値がない点。

この点に注意しつつ、データの利用用途3種類を見て意識するようにする。

  • Analyticsは、保存・変換済みのデータを使って、レポートやダッシュボードを作ったり、アドホック分析をしたりする段階。理想は、データチームに毎回依頼しなくても、事業部の人が自分でデータを見られる self-service analytics を実現すること。 Operational Analytics は、過去の傾向よりも「今どうなっているか」を重視する分析。たとえば、リアルタイム在庫やWebサービスの稼働状況など。 Embedded Analytics は、SaaSなどの製品の中に組み込まれた、顧客向けの分析機能。社内BIよりユーザー数が多くなりやすく、特に重要なのがアクセス制御(強すぎる権限をつけないようにすること)

  • MLも用途の一つ。用途として、Feature Storeがあり、これはML用の特徴量について、履歴・バージョン・チーム間共有などを管理する仕組み

MLにデータを提供する際には、

データ品質は十分か データサイエンティストがデータを発見できるか データエンジニアとMLエンジニアの責任範囲はどこか 学習データが現実を正しく表しているか、偏っていないか を考える必要がある。 また、MLを始める前に、まずちゃんとしたデータ基盤とAnalyticsを作るべき、基盤が弱ければMLはうまくいかない。

  • Reverse ETLは、分析基盤で作ったデータを業務システムへ戻すこと。salesforceから取ってきた情報を分析して、Churnしそうな人かのフラグをつけて、salesforceに戻すみたいな。SaaSや外部サービスの利用が増えたことで、Reverse ETLの重要性が上がっているらしい。
データエンジニアリングライフサイクルの共通要素
セキュリティ

セキュリティはデータエンジニアリング全体の前提であり、データエンジニアは単にデータを処理できればよいのではなく、誰がそのデータやシステムへアクセスできるかまで設計・管理する責任がある。

最小権限の原則→ユーザーやシステムに、その仕事を行うために必要最低限のデータ・リソースへのアクセス権だけを与えるという原則。また、これを自分に適応する意識も大切。、誤操作によるデータ削除や設定破壊を防ぐ意味もある。

データにアクセスできるすべての人が、「会社や顧客の機密データを守る責任がある」と理解している状態を作ることも大事。人や組織による事故が最も多いため。

アクセス権の設定時には、誰につけるかだけでなく、いつまでかの期間の縛りをつけることも重要。

データを守るという意味では、通信中のデータ(Data in flight)も、保存中のデータ(Data at rest)も守ることが大事。守る上では、暗号化、トークン化、データマスキングなどがある。

これらの観点から、データエンジニアにもセキュリティ管理能力が必要で、IAM(Identity and Access Management)の考え方が必要。

  • データマネジメント

データマネジメントとは、データや情報資産のライフサイクル全体を通して、価値を提供・管理・保護・向上させるための計画、方針、プログラム、実践を作り、実行し、監督すること

現在、元々は余裕がある大企業が行う考えと思われていたが、データツールの発展により、データエンジニアは単にパイプラインを作るだけでなく、「データを組織全体でどう適切に管理するか」という、より上位の問題に取り組むようになっている(データマネジメント)

データマネジメントは、データをどう管理すべきかで、データエンジニアリングは、実際にデータを扱う技術・実装な訳だが、データマネジメントもデータエンジニアはできないと、単なる技術者になってしまうという話。

データマネジメントには次のような要素がある

  • データガバナンス 組織のデータについて、品質・完全性・セキュリティ・使いやすさを保ち、データの価値を最大化するための管理の仕組み。人・プロセス・技術を組み合わせて実現する。特に重要な柱は 発見可能性 / セキュリティ / 説明可能性。ガバナンスが弱いと、「どのデータを使えばいいかわからない」「数字を信用できない」といった問題が起きる。

  • 発見可能性 と メタデータ 必要な人が、必要なデータをすぐ見つけ、その意味・出所・関連データを理解できることが重要。その基盤になるのが メタデータ(データについてのデータ)。Data Catalog、Lineageツール、Wikiなどを使って管理する。メタデータには主に4種類ある。 ビジネスメタデータ:用語の意味・定義・所有者・利用方法 テクニカルメタデータ:スキーマ、パイプライン、リネージュなどシステム上の情報 オペレーションメタデータ:実行ログ、Job ID、エラー、処理結果など リファレンスメタデータ:国コード、単位、社内コードなど他のデータを解釈するための基準

  • データの説明可能性・質・MDM データには誰が責任を持つかを明確にする必要がある。責任者は必ずしもデータエンジニアではなく、PMなどの場合もある。 データの質は「このデータを信頼できるか?」という問題で、主にAccuracy(正確性)・Completeness(完全性)・Timeliness(適時性)で評価する。単純な技術問題ではなく、「遅れて到着したデータをどう扱うか」などビジネス上のルール決めも必要。 また Master Data Management(MDM)では、顧客・商品・社員などの重要なエンティティについて、システムごとの違いを統一した Golden Record を作る。

  • データモデリング・デザイン データを分析・MLなどで使える形に設計すること。DBのテーブル設計だけでなく、APIのJSONやIoTデータのフォーマットなどもデータモデリングに含まれる。 データの種類や用途によって、正規化・非正規化、Kimball、Inmon、Data Vaultなど適切なモデルを選ぶ必要がある。モデリングを放棄すると、データは溜まっているのに誰も使えないデータスワンプ(データレイクに対して、こちらは何があるかわからない沼のようなイメージ)になりやすい。

  • データリネージュ データが、どこから来て、どのシステムを通り、どんな変換を受け、何に依存しているかを記録する仕組み。 エラー調査、デバッグ、責任追跡、監査・コンプライアンスに役立つ。たとえばユーザーから削除要求が来たとき、リネージュがあれば、その人のデータがどこに存在するか追跡できる。

  • データインテグレーション・相互運用性・オーケストレーション 現在のデータ基盤は1つの製品だけで完結せず、Salesforce → S3 → Snowflake → Sparkのように複数のシステムを接続して使うことが多い。最近は専用接続よりAPIによる連携も増えている。 個々の連携自体は簡単になった一方で、システム数とパイプライン全体の複雑さは増えているため、処理順序や依存関係を管理するオーケストレーションが重要になる。

  • データライフサイクルマネジメント データは保存するだけでなく、いつアーカイブし、いつ削除するかまで管理する必要がある。 Cloudでは保存量に応じて費用が発生するため、古いデータを安価なArchive Storageへ移すことが重要。またGDPRやCCPAのような法規制により、「忘れられる権利」に対応してユーザーデータを確実に削除できる仕組みも必要。ここでもメタデータ・カタログ・リネージュが重要になる。

  • データの倫理問題 データは実際の人間に影響するため、PrivacyやEthicsはSecurityと同様にデータライフサイクル全体で考える必要がある。データエンジニアは、PII(個人を特定できる情報)のマスキング、機密情報の保護、データ中のBiasの把握、GDPR・CCPAなどへの対応を意識する必要がある。

DataOps

DataOpsとは、Agile・DevOps・統計的プロセス管理(SPC)の考え方をデータ分野に適用したもの。 DevOpsがソフトウェアのリリース速度と品質を高めるのに対して、DataOpsはデータプロダクトの提供速度と品質を高めることを目指す。

DataOpsの目的は人・プロセス・技術を組み合わせて、Time to Valueを短くし、品質と生産性を高めること。

DataOpsは次の3つの柱から成り立っている

  • Automation DataOpsでは、変更管理・CI/CD・Configuration as Codeなどを使って、データ処理を安定・再現可能にする。さらにソフトウェアだけでなく、Data Quality、Data/Model Drift、Metadataの整合性まで確認する。成熟度イメージとしては、cronで定時実行 → Airflow/Dagsterなどで依存関係を管理 → DAGのテスト・デプロイまで自動化という流れ。目的は単なる自動化ではなく、人的ミスや運用負荷を減らし、より速く価値を提供すること。

  • Orchestrationの重要性 cronでは「前の処理が終わったか」を考慮せず固定時刻で実行するため、処理が遅れると後続処理が失敗したり、古いデータを使ったりする。 Orchestrationを使えば、依存するデータが準備できたら次の処理を開始するという制御ができ、より効率的で信頼性の高いPipelineを作れる。

  • Observability / Monitoring データの問題は、システム自体が動いていても気づきにくい。そのため、データとそれを生成するシステムの両方を継続的に監視することが重要。 Monitoringだけでなく、Logging / Alerting / Tracing / Observabilityを組み合わせて、異常を利用者より先に発見する必要がある。DODD(Data Observability Driven Development)では、Ingestion → Transformation → Analysisまでデータの状態を常に観測できることを重視する。

DataOpsは常に改善が前提で、ここはアジャイル開発っぽい?

データアーキテクチャ

組織の長期的なデータ活用を支えるために、現在と将来のデータシステム全体をどう構成するかを設計する考え方

このシステム構築時に、「一番高性能な技術を選ぶ」のではなく、Cost・運用のシンプルさ・性能・拡張性などのバランスを考える必要があるのがポイント。技術選定。この際に、今回のシステムには何が必要かというユースケースをよく考えることが重要。

オーケストレーション

オーケストレーションとは、複数のData Jobを、依存関係を考慮しながら、できるだけ効率よく実行・管理する仕組み。単なるスケジュール実行ではなく、Data Pipeline全体の流れを制御すること。

Orchestration Engineは、Job同士の依存関係を DAG として管理するので、スケジューラと違い実行順の管理が可能。

Job History、DAGのVisualization、Alertingに加えて、過去期間の処理を再実行する Backfill にも対応するので便利。この本では、オーケストレーションはbatch用として解説。streaming用だとさらに難しくなるため。

ソフトウェアエンジニアリング

データエンジニアリングには結局ソフトウェアエンジニアの知識が不可欠で、IaCやPipelines as Codeなどの能力が求められている。ツールが高度に抽象化されても、Data Engineerは「コードを書かなくてよくなる」のではなく、より高いレイヤでSoftware Engineeringを使うようになっているという話。今は生成AIが急激に発展しているから直のコードの難易度も下がってるけど、考え方は理解していないとダメという話。

これでようやく2章が終わり。疲れた。具体的な内容を知りたいのでそろそろ知らない知識を入れるようなフェーズに入りたい。