web-dev-qa-db-ja.com

トランザクションテーブルレコードをデータウェアハウスに転送するのに最適なETL設計

データウェアハウスに毎日データを入力する2種類のテーブルがあります。ルックアップテーブルまたは構成テーブルに数百のレコードがあり、テーブルを切り詰めて補充するだけで簡単です。

しかし、多くのレコードを持つトランザクションテーブルの場合、通常はインクリメントします。つまり、ETLを毎日実行して昨日のレコードを追加します。

私はいつも直面する2つの問題を抱えています

  1. なんらかの理由でジョブが失敗したとき(そのDaysトランザクションを失う)
  2. なんらかの理由でジョブが2回実行されるか、2回実行される(重複が発生する)場合

今、私はこれらの2つの問題を解決する方法を設計しようとしています。また、これらのイベントが発生した場合に自動的に修正できるようにETLを開発しようとしています。

欠落している日があるかどうかを確認し、その日にETLを実行し、重複がないかどうかを確認して削除したい。

以下は、私が1の方法ですが、私は過去5日間を取り込みます。ETLが毎日実行され、過去5日間を削除して補充します。 2.先月の日付が欠落していないか宛先表を確認し、欠落している日付をソースに照会します。

ソースは本番環境の巨大なテーブルであり、クエリを要求するときにクエリを最大限に最適化する必要があることを覚えておいてください。

ありがとう

5
AmmarR

トランザクションには監査タイムスタンプがありますか?上がるだけのものでなければなりません(遅れて到着する事実はありません。挿入/更新監査タイムスタンプはこれに適しています)
その場合、これを使用して抽出する範囲を定義できます。これは、この種の一般的なテクニックです。

  • 各抽出について、最初に、抽出する範囲を決定します(最小タイムスタンプmin_tsと最大タイムスタンプmax_tsを呼び出します)。
  • 抽出の開始時に、次のフィールドのある1行を別のテーブル(extraction_logと呼び、PKを付けます)に入れます。
  • Min_ts&max_tsを使用して、データを1回(_select * from where ts > min_ts and ts <= max_ts_)または必要に応じてチャンクで抽出します。
  • 抽出が成功したことを示し、ラインを更新して、ステータスを「Finished OK」に設定します

min_tsとmax_tsを決定する方法

  • 最後に成功したmax_tsを使用して、extraction_logからmin_tsを取得できます。 select max(max_ts) from extraction_log where status = 'Finished OK'

  • 抽出の開始時にソースデータベースからmax_tsを取得できます。 select max(audit_ts) from source_table

ここには代替案があります。これらを一時的なステージングテーブルに抽出する場合(ベストプラクティス)、あまりにも多くの時間(つまり、最後の5日間)を取り、後でODSのエントリを更新するときに重複に対処することもできます。 max_tsの場合、dwhとソースの間のクロックが同期しており、同期し続けることが確実である場合(これは非常に危険な仮定です-推奨されません)、sysdate()を使用することもできます。

技術的には、少ない労力で逃げることができます。ステータスや、各バッチを追跡する抽出ログテーブルは実際には必要ありません。しかし、このようにすると、後でデバッグやトラブルシューティングを行う際に非常に役立ちます。さらに、途中で失敗したロードからエントリを削除するルーチン、過去の抽出の範囲のギャップを見つけるルーチンなどが必要な場合は、extraction_logが役立ちます。 ODSの追加の列としてExtraction_idを含めることもできます。

さらにいくつかの考え

  • タイムスタンプの候補が適切でない場合は、同じプロパティを持つソースシステムの技術キー(上に移動する必要があり、遅れて到着する事実がない)も問題ありません。

  • タイムスタンプがソースアプリケーションによって生成され、まったく同じタイムスタンプを持つ2つのトランザクションが同時に挿入されないというリスクがある場合(かなり一般的)、わずかに過去のmax_tsを使用する方が安全です(select max(max_ts) - 5 minutes from source_table.

  • 失敗したロードについて。最後に失敗したロードのエントリのクリーンアップのみに関心がある場合は、それをETLフローの最初のステップとして追加できます。 (_delete from dwh_table where ts > min_ts_)これにより、最後に正常に抽出された後、失敗があればそのエントリが削除されます。それは、以前の成功した抽出の間の失敗を扱いません。

2
r.m

インポートしたトランザクションテーブルの維持に使用するデータウェアハウスにテーブルを追加できますか?

メンテナンステーブルは次のように呼び出すことができます。

ImportJob
    ImportID (primary key)
    TransactionDate

ImportID列をトランザクションテーブルに追加し、データのロード時にこれを設定します。

インポートテーブルには、インポートされるトランザクションの1日あたり1つのレコードが含まれます。 TransactionDateの一意の制約により、データが2回再ロードされるのを防ぐことができます。また、インポートが失敗した場合に、アトミックなトランザクションをすばやく削除する方法もあります。生産表に一度に1日のデータを照会し、欠落している日を埋めることができます。

1
sa555

さて、これは、コントロールテーブルを作成するために最初に必要なことの一種の基本的なバージョンになります。基本的に、これは実行しているETLを制御します。この表では、プロセスが最後に正常に実行されたときに格納したいものの1つです。これで、ETLを実行しているときに、このテーブルを呼び出して、基本的にすべての行を探している日付範囲を見つけることができます> LastSuccesfullRun

重複を防ぐために次に行うことも、かなり簡単です。最初に、最後に成功した実行に従って日付範囲でフィルターされたデータフロータスクを実行します。次に、検索コンポーネントを使用して、現在テーブルにある行セットと比較します。 MATCHでは、NO Match挿入では何も行いません。以下に添付されているのは、このためのデモです。

OLESource to Lookup

LookUp Table

No match

もっと詳しく説明したいのですが、ETLプロセスについて、アドバイスを提供するのに十分な知識がありません。

1
Zane

毎日の記録を個別の単位として扱うことができるようです。私は試してみます:

  1. SQLタスクまたはデータフローの実行-トランザクションがないDWから日付のリストを取得し、結果をレコードセット変数に入れます。
  2. コンテナごと-レコードセットをループして日付変数を入力します
  3. データフロー-where transactiondate >= @missingdate and transactiondate < dateadd(day,1,@missingdate)を使用してソースSQLを変数に構築します

そのため、ジョブが1〜2日遅れて実行された場合、ジョブは毎日個別にプロダクションにクエリを実行しますが、DWがすでに持っているレコードを取得するリソースを無駄にすることはありません。ジョブが1日に複数回実行される場合、トランザクションがない日(休日など)がない限り、本番に対してクエリが実行されることはありません。

上記の#1の日付範囲を過去5日間、30日間、または意味のあるものに制限することができます。

このアプローチの弱点は、日付リストに現在または将来の日付を含めることができないことと、DWに既にコピーされている日付の更新または新しいレコードが用意されていないことですが、ログに記録されたトランザクションでは、それは受け入れられるかもしれません。

1
SQLFox