Datawarehouse Design:結合された日付時間ディメンションと、個別の日付および時間ディメンションとタイムゾーン


10

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

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

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

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

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


1
この質問は、Stack Overflow:stackoverflow.com/questions/2507289/…にも存在します。
Jon of All Trades 2014

回答:


5

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

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


わかりました。ユーザーがタイムゾーンに基づいてデータをグループ化することはできませんが、これはおそらく、設計を簡略化するために私たちが利用できないものです。
Matt Palmerlee、2011年

@MattPalmerlee:ユーザーは、タイムゾーンをグループ化できます。通常はGeographyテーブルに含めますが、該当しない場合は、ファクトテーブルの属性として追加できます。
Jon of All Trades 2014

5

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

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

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


私はまた、あなたの解決策はおそらく、あまりにも複雑になり過ぎることなく、最も理にかなっていると思います。私は、timeZoneテーブルとあなたと同じようなTimeZoneBridgeを使用してDWをテストしています。また、TimeDimensionテーブルとDateDimensionテーブルもあります。date_key_local、time_key_local、およびtimezone_idにクラスター化インデックスを作成したので、TimeZoneBridgeを使用してローカル時間をUTC時間に変換するのが高速になります。
dsum

1
すべてのファクトテーブルの時間キーはutcになるため、utcを介してブリッジに参加します。 keys + tz id、それらにクラスター化インデックスを作成した方がうまくいく場合があります。ただし、ニーズに合った方法を実行してください。私の答えが誰かを助けてくれてうれしいです、私はそれが良いアプローチだと思います、そして私たちのすべてのテストから、それはまだかなり速いです、それはWHERE句になるとちょうど気を付けてください:あなたが望む日付範囲をできるだけ早くフィルターしてくださいクエリで可能です。
Matt Palmerlee、2007

これには日付のみが含まれますか?または、ファクトテーブルに86000の「日付/時間キー」値がある場合、ブリッジテーブルには86000行* n個のサポートされているタイムゾーンがあり、それはその1日だけですか?
アーロンバートランド

1
おそらく、あなたが持っている正確なテーブル定義を追加することができるので、読者は主要でユニークな制約を見ることができます。
ypercubeᵀᴹ

@AaronBertrandこれは、データを追跡する粒度(または選択した粒度)に依存します。この場合、ファクトテーブルで15分の粒度しか必要なかったため、サポートしたかったタイムゾーンごとに、1日あたり4 * 24 = 96レコードしかありません。これは完全に合理的です。
Matt Palmerlee、2014

2

統合された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フィールドには、日付と時刻のテーブルに参加します:

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バイトです。


それは創造的なアプローチです。ただし、組み合わせた日時の薄暗いテーブルには350,400行しかないと言うように、粒度をより細かい解像度に変更し始めると、数百万のレコードがすぐに取得されます。時間ディメンションとは別の日付ディメンションを選択した場合、時間ディメンションテーブルには48行のみ、日付ディメンションテーブルには1年あたり365行しかありません(または20年で7300行)。ファクトテーブルには、date_keyとtime_keyの列があります。これにより、日付の細分性のみを必要とするファクトテーブルがある場合にも、柔軟性が向上します。
Matt Palmerlee、2014

1
ディメンション内の100万行は私には関係ありません。データは10年に1回だけ変更され、PKのカバリングインデックスと2つまたは3つの最も使用頻度の高いフィールドは、サーバーRAMをわずかに消費します。ただし、SMALLINT10億行のファクトテーブルに6ダースを追加すると、12 GBにオーバーヘッドが加わり、実際の金額を話していることになります。日付を格納するだけでよい日付の場合は、もちろん、適切な日付の「12:00 AM」レコードを指すようにすることができます。
Jon of All Trades 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.