データ統合パイプラインのビルドインクリメンタルパイプラインハイパフォーマンスの維持

注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。

ハイパフォーマンスの維持

インクリメンタル・トランスフォームを使用することで、パイプラインが更新されるたびに新しい行だけが処理されるようにし、リソースの使用を最小限に抑えることができます。Foundryでは、インクリメンタル・トランスフォームはデータセットに新しい行を追加するだけで、行の置き換えや削除はできません。データの取り込みも同様のケースがあります。各実行で一般的に少量のデータが処理されるため、これらの追加は小さいですが、アクティブビューをレンダリングする際には、すべての追加がまとめて考慮されなければなりません。

通常は問題ありませんが、何十万、何百万もの小さな更新が蓄積された場合(これは、ビルドの頻度によっては、何週間も何ヶ月も経たないうちに起こることがあります)、読み込み性能が低下し始めることがあります。これは、以下で説明するいくつかの関連する要因によって引き起こされることがあります。

可能性のある原因

大量のファイル数

データセット内にファイルが多すぎると、現在のビューのデータにアクセスするバックエンドのリクエストが遅くなります。これにより、プレビューが利用できなくなる問題や、Contourでの障害、Pythonトランスフォームをはじめとするトランスフォームでの遅さが発生し、特にPythonトランスフォームでは、その言語環境でファイルをロードする際の特別なオーバーヘッドが発生します。

時間の経過とともに、アクティブなデータセットビューに関連する操作は、非効率的なデータ読み取りによって支配されるようになり、当初数分で実行されていたトランスフォームが、最終的には数時間や数日かかるようになります。極端な場合、バックエンドのリクエストがタイムアウトし、ビルドが失敗することもあります。

大量のトランザクション数

ファイルが多すぎるのと同様に、ビュー内にトランザクションが多すぎると遅さが発生します。ただし、この遅さは、ファイルが要求されるだけでなく、ビューの範囲が解決されるたびに発生し、統計の計算、履歴のロードなどのデータセット機能に影響を与える可能性があります。トランスフォームでは、この遅さは、環境がセットアップされるプリコンピュート段階、Sparkの詳細が利用可能になる前に現れるため、問題のデバッグが困難になります。

通常、トランザクションはファイルと一緒に蓄積されますが、場合によっては空のトランザクションが比較的低いファイル数で問題を引き起こすことがあります。逆に、比較的少ないトランザクション数でも、各トランザクションに多くのファイルが含まれている場合、ファイル数が多くなることがあります。

可能性のある解決策

定期的なスナップショット

インクリメンタルパイプラインのパフォーマンスを維持するための最も簡単で、場合によっては最も効果的な解決策は、定期的なスナップショットを実行することです。スナップショットでは、完全なデータを再処理し、出力を効率的にパーティション化できる新しいビューに置き換えます。スナップショットは計算が集中する操作であり、定期的な処理よりもインクリメンタル処理が好まれる理由ですが、たまにスナップショットを実行することで、同じビュー内にファイルやトランザクションが過剰に蓄積するのを防ぐことができます。スナップショットの頻度を決定する際には、データの読み書きのパフォーマンスをバランスさせるべきです。

スナップショット・トランザクションは、連鎖的な影響を持ち、スナップショットされた入力を使用するインクリメンタル・トランスフォームは、自身がスナップショットされます。インクリメンタル・トランスフォームを強制的にスナップショットで実行させるのではなく、トランスフォームの入力の1つをスナップショットし、トランスフォームアプリケーションがインクリメンタル・トランスフォームがスナップショットが必要であることを判断させるだけです。したがって、定期的にスナップショットを実行するインクリメンタル・パイプラインを設定するための便利な方法は、ダミーの入力を設定して、目的のスナップショット・スケジュールでビルドし、ダミーの入力を常にスナップショット・モードで実行させることです。

定期的なスナップショットには、以下のようないくつかの欠点があります。

  • スナップショットは、ダミーの入力が検索やフォルダー構造に表示されるため、データフローを複雑にすることがあります。
  • スナップショットは、頻繁に行われる場合、非常に費用がかかることがあります。
  • スナップショットが実行されている間は、パイプラインを通じて更新が伝播できず、SLA(サービスレベル契約)に影響を与えることがあります。
  • スナップショットは、Data Connectionの同期によってバックアップされた生のデータセットでは機能しません。
  • すべてのトランスフォームがスナップショットに対応しているわけではありません(ただし、常に対応しているべきです)。

データセットのプロジェクション

インクリメンタル・ビルドアップの対処法として最も推奨されるのは、関連するデータセットにデータセット・プロジェクションを追加することです。データセット・プロジェクションは、データセット内のデータを検索するための別のメカニズムを提供し、正規のデータセットとは独立して保存および更新されます。これらの特性のため、データセット・プロジェクションは、インクリメンタル計算の追加モデルから抜け出し、データの量が増えるにつれて内部データ表現を自動的に再構成することができます。これをコンパクションと呼びます。コンパクションにより、プロジェクションからの読み取りが常にパフォーマンスが良くなり、正規のデータセットにどれだけのファイルやトランザクションがあっても問題ありません。

これは、インクリメンタル・パイプラインに特に便利であり、データセット・プロジェクションは、正規のデータセットと完全に同期しなくても、読み取り者がパフォーマンス向上の恩恵を受けることができます。すべてのFoundry製品は、プロジェクションがなかった場合と同じようにビューを再構築するために、プロジェクションからのデータと正規のデータセットからのデータを組み合わせる方法を知っています。例えば、データセットに100のインクリメンタル・トランザクションがあり、最初の99で構築されたプロジェクションがある場合、99はプロジェクションから読み取られ、データセットからは1つだけ読み取られます。このため、データセット・プロジェクションは通常、1日または1週間に1回更新するだけで十分であり、非常に計算コストがかからない状態で維持できます。

データセット・プロジェクションは正規のデータセットとは別のリソースであるため、いつでも構築することができます。たとえば、データセットがトランザクション10を構築していて、プロジェクションが同時に構築を開始した場合、プロジェクションはトランザクション9から読み取ります。このシナリオでデータをクエリする読み取り者は、プロジェクションからトランザクション1〜8、データセットからトランザクション9を読み取り、データセットから直接読み取る場合と同じデータを見ることができます。

データセット・プロジェクションの欠点には以下のようなものがあります。

  • データセット・プロジェクションは、データセットだけでは使用しないよりも多くのストレージを使用します。
  • データセット・プロジェクションは、Foundry Retentionとは標準で動作しません。
  • データセット・プロジェクションは、正規のデータセットを何らかの方法で変更しません(したがって、プロジェクションが削除されると、再び読み取りが非効率的になります)。

保持ポリシー

パイプラインのユースケースでは、プラットフォーム内での履歴データの保持が必要ないことがあり、最新のトランザクションだけを保持するだけで問題ありません。これは、Foundry Retentionを使用して自動的に行うことができます。この場合、トランスフォームのロジックにトランザクション間の依存関係(集約や差分計算など)が含まれていない限り、インクリメンタル・パイプラインを特別な考慮なしに構築することができます。Pythonトランスフォームでは、インクリメンタルデコレータに allow_retention フラグを設定する必要があります(そうしないと、DELETE トランザクションがスナップショット実行をトリガーします)。

保持ポリシーの変更に伴う欠点には以下のようなものがあります。

  • 履歴データの消失。
  • トランザクションがデータの観点から独立した単位でない場合、保持ポリシーは一貫性のない状態につながる可能性があります(例えば、開始イベントと一致しない終了イベントが発生することがあります)。

検討すべき追加のオプション

トランザクションの中止

場合によっては、トランザクションがゼロファイルでコミットされることがありますし、空のファイルだけでコミットされることもあります。これらのトランザクションはビューに影響を与えませんが、有効な更新と見なされ、スケジュールや関連する副作用がトリガーされるため、計算の無駄になる可能性があります。空のトランザクションは、ファイルやトランザクションの数を大幅に増加させることがあります。

空のトランザクションは、原則として、データ・コネクション sync などのソースで回避することが最善です。データ・コネクションは常にファイルのないトランザクションを中止しますが、空のファイルはまだ生成されることがあります。空のトランザクションは、カスタムプラグインで特に問題となることがあり、場合によってはプラグインを変更して空のトランザクションを回避できないことがあります(たとえば、データ・コネクションのインクリメンタル・メタデータを更新するために、空でないトランザクションが必要な場合など)。他の場合では、トランスフォームやその他の手段で、ファイルのないトランザクションがコミットされることがあります。

これらの空のトランザクションやファイルのないトランザクションの影響を最小限に抑えるために、パイプラインで最も上流のトランスフォームでトランザクションを明示的に中止することができます。空の入力を受け取った場合、または空の出力が得られた場合に、出力オブジェクトに対して .abort() を呼び出すことができます。これにより、ジョブが中止され、トランザクションも中止されます。中止されたトランザクションは、事実上キャンセルされ、スケジュールがトリガーされることも、副作用が発生することもありません。トランザクションを中止すると、空のトランザクションがパイプラインを下流に伝播するのを止めることができます。また、トランザクションの中止は、失敗統計に寄与しない(一方で、意図的にビルドを失敗させると、失敗統計に寄与する)。

中止されたビルドは成功と見なされ、入力トランザクションポインタが進みます。そのため、空でない入力で中止すると、データが破棄されることになります。これは、別の理由でビルドを停止したい場合(前提条件が満たされないなど)には望ましくない結果となります。

変更履歴データセット

変更履歴ロジックを使用すると、追加のみのトランザクションに編集セマンティクスを実装できるようになり、インクリメンタル・パイプラインで結合や集約を確実に実行できるようになります。ただし、前述のファイル数やトランザクション数の問題に加えて、追加のみのトランザクションに編集セマンティクスを実装することで、行数が増加し続け、州解決段階に達すると(またはスタンドアロンのスナップショットが必要になると)、トランスフォームのパフォーマンスが次第に悪化することがあります。

このようなパイプラインの行数を制御するのは少しトリッキーです。スナップショットは可能であり、部分状態が存在するときの中間トランスフォームでは大いに役立ちます(これらは、完全なリビルドでほとんど消え去ります)。しかし、スナップショットを完全に活用するためには、ロジックが行を最新の状態にまとめる必要があり、これは常に望ましいわけではありません(いくつかのケースでは、特定の時点での行の状態を求めるのではなく、最新の状態を求めることがあります)。データセット・プロジェクションはある程度しか助けになりません。そして、行が原子単位でない場合、保持ポリシーが望ましい効果を持たないことがあります(例えば、開始イベントと一致しない終了イベントが発生する場合)。そのため、このようなパイプラインを設計する際には特別な注意が必要です。