web-dev-qa-db-ja.com

データウェアハウスの設計:日付と時刻の組み合わせディメンションと、日付と時刻の個別のディメンションおよびタイムゾーンの組み合わせ

新しいデータウェアハウスの設計を開始したばかりで、日付と時刻のディメンションがどのように機能するかを設計しようとしています。複数のタイムゾーン(おそらく、少なくともGMT、IST、PST、EST)をサポートできる必要があります。最初は、1つの広い結合された日時ディメンションを15分程度まで細かくすることを考えていました。これにより、ファクトテーブルに1つのキーがあり、サポートされているすべてのタイムゾーンのすべての異なる日時データが1つのディメンションテーブルにあります。 (つまり、日付キー、GMT日付、GMT時間、IST日付、IST時間など...)

キンボールは、テーブルが大きくなりすぎないように(データウェアハウスツールキットp。240)、時間ディメンションとは別の日ディメンションを使用することを推奨していますが、これは、各タイムゾーンのファクトテーブルに2つのキーがあることを意味します。サポートする必要があります(1つは日付用、もう1つは時刻用)。

私はこの領域で非常に経験が浅いので、誰かが2つのアプローチ間のトレードオフ、つまりパフォーマンスとすべての異なるタイムゾーンキーの管理のトレードオフを知っていることを望んでいます。多分他のアプローチもあるかもしれませんが、ファクトテーブルにタイムゾーンごとに別の行があることを話している人を見たことがありますが、ファクトテーブルが数百万の行である場合、タイムゾーンを追加するために4倍にする必要があるという問題のようです。

15分の粒度を使用すると、日付時刻ディメンションテーブルに1年あたり131,400(24 * 15 * 365)行が含まれます。これは、パフォーマンスにとってそれほどひどく聞こえませんが、いくつかをテストするまではわかりません。プロトタイプクエリ。ファクトテーブルに個別のタイムゾーンキーがあることの他の問題は、クエリが目的のタイムゾーンに基づいてディメンションテーブルを別の列に結合する必要があることです。これはおそらくSSASが処理するものですが、よくわかりません。

どんな考えにも感謝します、-Matt

10
Matt Palmerlee

日付と時刻を別々にすると、時間による集計を非常に簡単に行うことができます。たとえば、クエリを実行して、1日の中で最も忙しい時間帯を見つけたい場合などです。これは、別の時間ディメンションを使用して非常に簡単に実行できます。

また、タイムキーは1つだけにする必要があります。 GMT/EST時間のどちらかを決定します。次に、これをファクトテーブルで使用します。他のタイムゾーンに基づいてレポートを実行する必要がある場合は、アプリケーションまたはクエリで変換するだけです。

DataWarehouseを実装して複数のタイムゾーンをサポートし、できるだけ効率的にすることを決定した方法のフォローアップです。「タイムゾーン」だけでなく、タイムゾーン(ID、名前など)のテーブルを作成することにしました。次のような「ブリッジ」テーブル:

time_zone_bridge
---------------
date_key_utc
time_key_utc
timezone_id
date_key_local
time_key_local

このようにして、通常の日付と時刻のディメンションテーブルを小さく保ち、すべてのファクトをUTCの日付/時刻キーにリンクし、別のタイムゾーンでレポート/グループ化する必要がある場合は、タイムゾーンブリッジテーブルを介して結合する必要があります。ローカルの日付/時刻キーを日付と時刻のディメンションテーブルにリンクします。これはSSISから呼び出されたC#コードを使用してタイムゾーンブリッジテーブルを作成します。これは、SqlServerから直接TZを行うよりもはるかに複雑ではないためです。

5
Matt Palmerlee

統合されたDateTimeディメンションを使用する倉庫のアイデアが拒否されたのを見てきましたが、その理由がはっきりしていません。少し簡略化して、ここで私が現在作成しているファクトテーブルを示します。

Transactions
(
...
CreatedDateTimeSK         INT NOT NULL,  -- Four bytes per date...
AuthorizedDateTimeSK      INT NOT NULL,
BatchSubmittedDateTimeSK  INT NOT NULL,
BatchApprovedDateTimeSK   INT NOT NULL,
SettlementDateTimeSK      INT NOT NULL,
LocalTimeZoneSK           TINYINT NOT NULL  -- ...plus one byte for the time zone
)

DateTimeフィールドは、DateTimeテーブルに結合します。

DateTimes
(
DateTimeSK   INT NOT NULL PRIMARY KEY,
SQLDate      DATE NOT NULL,
SQLDateTime  DATETIME2(0) NOT NULL,
Year         SMALLINT NOT NULL,
Month        TINYINT NOT NULL,
Day          TINYINT NOT NULL,
Hour         TINYINT NOT NULL,
Minute       TINYINT NOT NULL CHECK (Minute IN (0, 30)),
...
)

これは30分単位の解像度なので、1日あたり48レコード、20年間で350,400となり、非常に扱いやすいです。

イベントの日付/時刻は格納時にUTCに変換されますが、LocalTimeZoneSKフィールドとブリッジテーブルを使用すると、簡単に結合して現地時間を取得できます。

TimeZoneBridge
(
DateTimeSK       INT NOT NULL,
TimeZoneSK       TINYINT NOT NULL,
PRIMARY KEY (DateTimeSK, TimeZoneSK),
LocalDateTimeSK  INT NOT NULL
)

今日作成されたトランザクションを取得するには、UTC時間:

SELECT COUNT(*)
FROM Transactions AS T
  INNER JOIN DateTimes AS CD ON T.CreatedDateTimeSK = CD.DateTimeSK
WHERE CD.SQLDate = '2014-08-22'

今日作成されたトランザクションを、トランザクションの現地時間で取得するには:

SELECT COUNT(*)
FROM Transactions AS T
  INNER JOIN TimeZoneBridge AS TZB ON T.CreatedDateTimeSK = TZB.DateTimeSK AND T.TimeZoneSK = TZB.TimeZoneSK
  INNER JOIN DateTimes AS CD ON TZB.LocalDateTimeSK = CD.DateTimeSK
WHERE CD.SQLDate = '2014-08-22'

TimeZoneSKREALオフセット(たとえば、米国中部夏時間の場合は-5.0)に置き換えることで、物事を簡素化したくなるかもしれませんが、これは、ファクトの日付/時刻があると故障します。レコードは夏時間にあり、一部はそうではありません。

ファクトレコードのイベントが、出荷やフライトなどの異なるタイムゾーンで発生する可能性がある場合は、日付ごとにタイムゾーンフィールドが必要であり、日付あたり最大5バイトです。

2