履歴テーブルに参加する

出力で美しい履歴間隔を取得するために、既存のDBMSのフレームワーク内で2つ以上の履歴テーブルを相互に接続する必要がある場合、時々タスクを処理する必要があります。 なんで? そのため、レポートは、ユーザーが選択した日付のデータ、または処理のためにこれらのデータを取得したアプリケーションを正しく表示できます。

多くの場合、ワークショップの同僚や兄弟は同様のタスクに直面し、それらを解決する最善の方法をアドバイスします。

この記事では、このタイプのさまざまな状況がどのように解決されたかについての私の経験を共有したいと思います。



「履歴表」というフレーズを言うとき、私はすぐに言及します

SCDタイプ2またはSCDタイプ6



また、主にデータウェアハウスについても説明します。 ただし、以下で説明するアプローチの一部はOLTPソリューションに適用されます。 結合されたテーブルでは、参照整合性は自然な方法で、または起動時に損失値(キーを持つ値ですが、変数属性のデフォルト値)を生成することで維持されると想定されます。



2つのテーブルがあり、それぞれが属性を変更するキーを持ち、レコードの間隔の日付があるように見えます。キーで結合し、間隔を置いて何かを考えます。 しかし、それほど単純ではありません。

視覚的には、タスクは次のとおりです。



画像



しかし、最適な方法で結果を達成する方法は、状況によって異なります。



オプション1-すべてが「オンザフライ」で読み取れるたびに、データもテーブルもあまりありません


このオプションでは、テーブル間の結合を含むビューを作成できますが、間隔の交差を考慮します。



接続条件は、次のように概略的に説明できます。



First_Table.Start_dt <= Second_Table.End_dt AND Second_Table.Start_dt <= First_Table.End_dt







ここで、読者は頭の中でこれを想像し始めて、この条件によって考慮されないかもしれないオプションを計算できます。 交差する間隔のグラフィカルに可能なオプションは次のようになります。



画像



オプションは、場所で「間隔A」と「間隔B」を変更した場合にも当てはまります。 そしてもちろん、任意の間隔の終わりを開くことができます。 設計の質問がどのように開いているか(無限に長い日付が選択されているかNULLであるか)はソリューションの基本ではありませんが、SQLを記述するときは、システムにどのオプションがあるかを考慮する必要があります。



好奇心が強い人はチェックできます-条件はすべてのオプションをカバーしています。



ただし、異なるテーブルの2つの行を同様の方法で結合した結果、2つの開始日と2つの終了日が得られます。 それらから何かを選択する必要があります。 2つの交差する間隔を接続して得られる結果の間隔では、境界は2つの開始日の最大値と2つの終了日の最小値として計算されます。 Oracle DBMS関数に関しては、これはそれぞれGREATEST(Start_DT)とLEAST(End_DT)のように聞こえます。 結果として得られる間隔は、3番目のテーブルに接続できます。 接続の結果は、結果の開始日と終了日を計算した後、4番目のテーブルなどに接続できます。



使用するDBMSに応じて、SQLの報酬は異なりますが、結果は正しいものです。 CREATE VIEWでラップして結果のショーケースを作成するだけで、消費者(レポート、アプリケーション、ユーザー)がアクセスして関連する関連日付を示します。



オプション2-大量のデータ


大量のデータがあり、第1の実施形態で説明した通常の表現を使用してもパフォーマンス要件、つまり代替要件が満たされない場合、ストアフロントを段階的に計算できます。 はい、ストアフロントの計算結果をテーブルに保存し、データコンシューマーをテーブルに送信することについて話します。



データをいつどのように計算しますか? 詳細データのダウンロードが完了するたびに。

この場合、タスクはささいなものになります。主なことは、ロードしたばかりのデータの営業日(レポート日付、関連日付、誰がそれを呼び出すか)を知ることです。 これは、これらのプロセスを制御するETL \ ELTフレームワークのタスクです。 日付(または個別の日付セット)に関心があります。 入力として日付または日付のセットをとるプロシージャが作成されます(保存されているか、ETL \ ELTで、これはすでに宗教によって決定されています)。 そして、ループ内で、SQLの実行を開始します。SQLは、キーによって必要なすべてのテーブルを結合し、各履歴テーブルにフォームの条件を課します: WHERE Input_Date BETWEEN Current_Table.Start_DT and Current_Table.End_DT



。 私が今まで見たほとんどのシステムでこの種のSQLは、非常に高速に動作します。 レコードは非常に選択的な条件でフィルタリングされ、すぐに接続されます。

変更が強調表示されるメカニズムに従って、結果はすでにウィンドウに配置されています。 ショーケースはSCDタイプ2またはSCDタイプ6の本質であるため、結果のレコードが変更されているかどうかを確認する必要があります。



このオプションの欠点は、「アイドル」で大量の作業を実行できることです。 たとえば、ロードされた日付のデータに変更はありませんでしたが、その日付のすべてのデータのスナップショットを作成し、ストアフロントと比較します。 その後、行の0.1%のみで変更が発生または発生していないことがわかります。



オプション3-データモデルは1つの(または限られた)キーの周りの「スノーフレーク」を表し、大量のデータが存在する場合もあります。


このオプションは、第3正規形に近いモデルを持つデータウェアハウスで一般的です。

モデルの回路図バージョンは次のようになります。



画像



このようなスキームを使用すると、計算プロセスを最適化し、実際の変更があった日付のみを日付のセット全体から選択することができます。 どうやって? はい、それは非常に簡単です-すべてのテーブルからKey_idとStart_dtの一意の組み合わせを選択します。 つまり Key_idとStart_dtの組み合わせからのUNION(UNION ALLではないことに注意)。 UNION ALLからUNIONまたはDISTINCTを選択する(またはDISTINCTからUNION ALLを選択する)は、使用するDBMSと開発者の宗教によって異なります。

そのようなリクエストの結果として、これらのキーに何かが起こったときのキーと日付のセットを取得します。 さらに、取得されたセットは、Key_idが等しいという条件下でテーブルに接続され、特定のテーブルの記録レコード間隔で取得されたStart_dtが発生します。 少なくとも一度はリポジトリに落ちたため、多くの人はこのサンプルに絶対にすべてのキーが存在すると推測します。 ただし、物理データモデルで特定のKey_idのクエリパフォーマンスを提供できる場合、このようなオプションはパフォーマンスの面で有利です。 また、状態を頻繁に変更するKey_idの重要なサブセットがある場合。



説明されているオプションは、2つの方法で実装できます(DBMSとデータ量に依存)。 これは、WITH句を使用してビューで実行できます(Oracleの場合は、 -+プロセスを高速化するために具体化することもできます)。 実際、中間テーブルは1つの大きな(一時的な)テーブルであり、キーの組み合わせがデータ型と一致する場合に多くのストアフロントで使用できます。 つまり 手順の最初のステップで選択が行われ、その結果がテーブルに保存されます。 2番目のステップでは、ステップ1のテーブルが詳細データと結合されます。 この特定のケースで正当化される場合、ステップ1.5はテーブルの統計の収集である場合があります。



開発者と顧客の生活と想像力がはるかに豊かであるため、より多くのオプションがありますが、少なくともこれらの説明されたオプションが誰かが時間を節約するのに役立つか、さらに最適なソリューションを作成するための基礎になることを願っています。



All Articles