Progettazione del datawarehouse: dimensione data / ora combinata rispetto a dimensioni e fusi orari separati di giorno e ora


10

Stiamo appena iniziando a progettare un nuovo data warehouse e stiamo provando a progettare come funzioneranno le nostre dimensioni di data e ora. Dobbiamo essere in grado di supportare più fusi orari (probabilmente almeno GMT, IST, PST ed EST). Inizialmente pensavamo che avremmo avuto una dimensione data / ora combinata ampia fino a una granularità di circa 15 minuti, in questo modo abbiamo una chiave nelle nostre tabelle dei fatti e tutti i diversi dati di data e ora per tutti i fusi orari supportati sono in una tabella delle dimensioni. (ad es. chiave della data, data GMT, ora GMT, data IST, ora IST, ecc ...)

Kimball suggerisce di avere una dimensione del giorno separata dalla dimensione dell'ora del giorno per evitare che la tabella diventi troppo grande (Il toolkit di data warehouse p. 240) che suona bene, tuttavia ciò significherebbe che abbiamo due chiavi nelle nostre tabelle dei fatti per ogni fuso orario abbiamo bisogno di supporto (uno per la data e uno per l'ora del giorno).

Poiché sono molto inesperto in questo settore, spero che qualcuno là fuori conosca i compromessi tra i due approcci, ovvero le prestazioni rispetto alla gestione di tutte le diverse chiavi di fuso orario. Forse ci sono anche altri approcci, ho visto alcune persone parlare di avere una riga separata nella tabella dei fatti per fuso orario, ma sembra un problema se le tabelle dei fatti sono milioni di righe quindi è necessario quadruplicarle per aggiungere fusi orari .

Se eseguiamo il grano di 15 minuti, avremo 131.400 (24 * 15 * 365) righe all'anno nella nostra tabella delle dimensioni della data e dell'ora che non sembrano troppo orribili per le prestazioni ma non lo sapremo con certezza fino a quando non ne verificheremo alcune query prototipo. L'altra preoccupazione di avere chiavi di fuso orario separate nella tabella dei fatti è che la query deve unire la tabella delle dimensioni a una colonna diversa in base al fuso orario desiderato, forse questo è qualcosa che SSAS si prende cura di te, non sono sicuro .

grazie per ogni pensiero, -Matt


1
Questa domanda esiste anche in Stack Overflow: stackoverflow.com/questions/2507289/… .
Jon of All Trades,

Risposte:


5

La data e l'ora separate ti permetteranno di fare aggregati per tempo molto facilmente. ad esempio: se si desidera eseguire una query per trovare il periodo di tempo della giornata più occupato. Questo è molto facile da eseguire usando una dimensione temporale separata.

Inoltre, dovresti avere solo un timekey. Decidi l'ora GMT / EST - quindi usala nella tabella dei fatti. Se è necessario eseguire report basati sull'altro fuso orario, è sufficiente convertirlo nell'applicazione o nella query.


Ok, questo ha senso, gli utenti non possono raggruppare i dati in base al loro fuso orario, ma è probabilmente qualcosa di cui non potremmo vivere per semplificare la progettazione.
Matt Palmerlee,

@MattPalmerlee: gli utenti possono raggruppare per fuso orario se glielo dai. Normalmente lo includerei nella Geographytabella, ma se nessuno si applica è possibile aggiungerlo come attributo della tabella dei fatti.
Jon of All Trades,

5

Solo un seguito su come abbiamo deciso di implementare il nostro DataWarehouse per supportare più fusi orari ed essere il più efficiente possibile: abbiamo scelto di creare una tabella di fusi orari (id, nome, ecc ...) e un "fuso orario bridge "che assomiglia a questo:

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

In questo modo possiamo mantenere piccole le nostre normali tabelle delle dimensioni di data e ora, tutti i nostri fatti si collegano alle chiavi di data / ora UTC, quindi se dobbiamo segnalare / raggruppare in base a un fuso orario diverso, dobbiamo solo unirci attraverso la tabella bridge del fuso orario e collegare le chiavi locali di data / ora alle tabelle delle dimensioni di data e ora. Popoliamo la nostra tabella bridge del fuso orario usando il codice C # richiamato da SSIS poiché questo era molto meno complicato rispetto a fare cose TZ direttamente da SqlServer.


Penso anche che la tua soluzione abbia probabilmente più senso senza entrare in qualcosa di troppo complicato. Sto testando il mio DW usando una tabella timeZone e TimeZoneBridge simili alla tua. Ha anche le tabelle TimeDimension e DateDimension. Ho creato un indice cluster su date_key_local, time_key_local e timezone_id, in modo che la conversione dell'ora locale in ora UTC utilizzando TimeZoneBridge sarebbe veloce.
domenica

1
La nostra chiave cluster primaria per la tabella bridge è nelle colonne data / ora utc + id fuso orario (se ricordo bene), poiché tutte le chiavi temporali delle tabelle dei fatti saranno in utc, ti unirai al bridge attraverso utc keys + tz id, potrebbe funzionare meglio avere l'indice cluster su quelli. Fai comunque ciò che ha senso per le tue esigenze. Sono contento che la mia risposta abbia aiutato qualcuno, penso che sia un buon approccio e da tutti i nostri test, è ancora ragionevolmente veloce, fai solo attenzione quando si tratta della clausola WHERE: filtra gli intervalli di date desiderati già dal possibile nelle tue domande.
Matt Palmerlee,

Questo contiene solo date intere? O se nella tabella dei fatti sono presenti 86000 valori "chiave data / ora", la tabella bridge avrà 86000 righe * n fusi orari supportati, e questo è solo per quel giorno?
Aaron Bertrand

1
forse puoi aggiungere la definizione esatta della tabella che hai, in modo che i lettori possano vedere i vincoli primari e unici.
ypercubeᵀᴹ

@AaronBertrand dipende dalla granulosità (o dalla granularità scelta) su cui tracciare i dati, nel nostro caso abbiamo solo bisogno di una granularità di 15 minuti nelle nostre tabelle dei fatti, quindi sono solo 4 * 24 = 96 record al giorno per fuso orario che volevamo supportare, che è completamente ragionevole.
Matt Palmerlee,

2

Ho visto DateTimerespinta l'idea di un magazzino che utilizza una dimensione combinata , ma non ho visto un motivo molto chiaro per cui. Semplificando leggermente, ecco la tabella dei fatti che sto costruendo proprio ora:

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
)

I DateTimecampi si uniscono a una tabella 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)),
...
)

Questo è ad una risoluzione di mezz'ora, quindi ci sono 48 registrazioni al giorno, 350.400 in 20 anni - abbastanza gestibili.

La data / ora dell'evento vengono tradotte in UTC quando memorizzate, ma con il LocalTimeZoneSKcampo e una tabella bridge possiamo facilmente unirci per ottenere l'ora locale:

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

Per ottenere transazioni create oggi, ora UTC:

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

Per ottenere le transazioni create oggi, nell'ora locale per la transazione:

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'

Potresti essere tentato di semplificare le cose sostituendo TimeZoneSKcon un REALoffset (ad esempio, -5,0 per l'ora legale degli Stati Uniti centrale), ma ciò si interromperà se alcune date / ore per un record di fatti sono in ora legale e altre no.

Se gli eventi per un record di fatti possono accadere in diversi fusi orari, come una spedizione o un volo, è necessario un campo del fuso orario per ogni data e si arriva a un massimo di cinque byte per data.


È un approccio creativo. Tuttavia, come dici tu avrai solo 350.400 righe nella tua tabella dim datetime combinata, se inizi a cambiare la grana per una risoluzione più fine, entrerai rapidamente nei milioni di record. Se si sceglie di avere una dimensione data separata rispetto alla dimensione temporale, si hanno solo 48 righe nella tabella della dimensione temporale e solo 365 righe all'anno nella tabella delle dimensioni della data (o 7300 righe in 20 anni). La tabella dei fatti ha quindi semplicemente una colonna per date_key e time_key. Ciò lo rende anche più flessibile se si dispone di alcune tabelle dei fatti che richiedono solo la granularità della data.
Matt Palmerlee,

1
Un milione di righe in una dimensione non mi riguardano: i dati vengono modificati solo una volta ogni dieci anni e un indice di copertura sul PK e due o tre campi più utilizzati occuperanno una quantità banale di RAM del server. Tuttavia, l'aggiunta di mezza dozzina di SMALLINTs a una tabella dei fatti da un miliardo di righe equivale a 12 GB più spese generali, e ora stai parlando di soldi veri. Per le date che devono solo memorizzare la data, puoi ovviamente indicarle nel record "12:00 AM" per la data appropriata.
Jon of All Trades,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.