การออกแบบคลังข้อมูล: มิติเวลาวันที่แบบรวมเทียบกับมิติและวันและเวลาที่แยกจากกัน


10

เราเพิ่งเริ่มออกแบบคลังข้อมูลใหม่และเราพยายามออกแบบวิธีการทำงานของวันที่และเวลา เราต้องสามารถรองรับหลายเขตเวลา (อาจอย่างน้อย GMT, IST, PST และ EST) ตอนแรกเราคิดว่าเราจะมีมิติเวลาวันที่ที่รวมกันกว้างลงไปจนถึง 15 นาทีอย่างละเอียดด้วยวิธีนี้เรามีหนึ่งคีย์ในตารางข้อเท็จจริงของเราและข้อมูลวันที่ที่แตกต่างกันทั้งหมดสำหรับเขตเวลาที่สนับสนุนทั้งหมดอยู่ในตารางมิติหนึ่ง (เช่นรหัสวันที่, วันที่ GMT, เวลา GMT, วันที่ IST, เวลา IST, ฯลฯ ... )

Kimball แนะนำให้มีการแยกมิติวันจากช่วงเวลาของวันเพื่อป้องกันไม่ให้ตารางขยายตัวใหญ่เกินไป (ชุดเครื่องมือคลังข้อมูลหน้า 240) ซึ่งฟังดูดี แต่นั่นหมายความว่าเรามีสองปุ่มในตารางความเป็นจริงสำหรับแต่ละเขตเวลา เราต้องการการสนับสนุน (หนึ่งสำหรับวันที่และหนึ่งสำหรับช่วงเวลาของวัน)

เนื่องจากฉันไม่มีประสบการณ์มากในพื้นที่นี้ฉันหวังว่าจะมีใครบางคนรู้ว่าการแลกเปลี่ยนระหว่างสองวิธีคือประสิทธิภาพและการจัดการของคีย์โซนเวลาที่แตกต่างกันทั้งหมด อาจมีวิธีอื่นด้วยเช่นกันฉันเคยเห็นบางคนกำลังพูดถึงการแยกแถวในตารางความเป็นจริงต่อเขตเวลา แต่ดูเหมือนว่าจะมีปัญหาหากคุณข้อเท็จจริงว่าตารางมีจำนวนหลายล้านแถวคุณต้องเพิ่มสี่เท่าเพื่อเพิ่มเขตเวลา .

ถ้าเราทำธัญพืช 15 นาทีเราจะมีแถว 131,400 (24 * 15 * 365) ต่อปีในตารางมิติเวลาวันที่ซึ่งไม่ฟังดูน่าเกลียดเกินไปสำหรับการแสดง แต่เราไม่รู้แน่ชัดจนกระทั่งเราทดสอบบางอย่าง แบบสอบถามต้นแบบ ข้อกังวลอื่น ๆ เกี่ยวกับการมีคีย์โซนเวลาแยกต่างหากในตารางข้อเท็จจริงคือแบบสอบถามต้องเข้าร่วมตารางมิติกับคอลัมน์อื่นตามเขตเวลาที่ต้องการบางทีนี่อาจเป็นสิ่งที่ SSAS ดูแลคุณฉันไม่แน่ใจ .

ขอบคุณสำหรับความคิดใด ๆ -Matt


1
คำถามนี้ยังมีอยู่ในกองมากเกิน: stackoverflow.com/questions/2507289/...
Jon of All Trades

คำตอบ:


5

การมีวันที่และเวลาแยกกันจะช่วยให้คุณสามารถรวบรวมตามเวลาได้อย่างง่ายดาย สำหรับเช่น: หากคุณต้องการเรียกใช้แบบสอบถามเพื่อค้นหาว่าช่วงเวลาใดของวันที่ยุ่งที่สุด สิ่งนี้สามารถทำได้ง่ายมากโดยใช้มิติเวลาแยกกัน

นอกจากนี้คุณควรมีเวลาหนึ่งครั้ง ตัดสินใจเลือกเวลา GMT / EST จากนั้นใช้ในตารางข้อเท็จจริง หากคุณต้องการเรียกใช้รายงานตามเขตเวลาอื่นเพียงแปลงในแอปพลิเคชันหรือแบบสอบถามของคุณ


ตกลงนั่นสมเหตุสมผลแล้วผู้ใช้ไม่สามารถจัดกลุ่มข้อมูลตามเขตเวลาของพวกเขาได้ แต่นั่นอาจเป็นสิ่งที่เราสามารถมีชีวิตอยู่ได้โดยไม่ต้องทำให้การออกแบบง่ายขึ้น
Matt Palmerlee

@MattPalmerlee: ผู้ใช้สามารถจัดกลุ่มตามโซนเวลาถ้าคุณให้กับพวกเขา โดยทั่วไปแล้วฉันจะรวมไว้ในGeographyตาราง แต่ถ้าไม่มีคุณสามารถเพิ่มเป็นคุณลักษณะของตารางความจริงของคุณ
Jon of All Trades

5

เพียงแค่ติดตามวิธีที่เราตัดสินใจใช้ DataWarehouse ของเราเพื่อสนับสนุนเขตเวลาหลายแห่งและมีประสิทธิภาพมากที่สุด: เราเลือกที่จะสร้างตารางของเขตเวลา (id, ชื่อ, ฯลฯ ... ) รวมถึง "เขตเวลา" บริดจ์ "ตารางที่มีลักษณะดังนี้:

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

ด้วยวิธีนี้เราสามารถทำให้ตารางวันที่และเวลาปกติของเรามีขนาดเล็กข้อเท็จจริงทั้งหมดของเราเชื่อมโยงไปยังปุ่มวันที่ / เวลา UTC จากนั้นถ้าเราต้องการรายงาน / กลุ่มตามโซนเวลาที่แตกต่างกัน และเชื่อมโยงปุ่มวันที่ / เวลาท้องถิ่นกลับไปที่ตารางวันที่และเวลา เราเติมข้อมูลตารางบริดจ์โซนเวลาโดยใช้รหัส C # ที่เรียกใช้จาก SSIS เนื่องจากมีความซับซ้อนน้อยกว่าการทำข้อมูล TZ จาก SqlServer โดยตรง


ฉันก็คิดว่าวิธีแก้ปัญหาของคุณน่าจะเหมาะสมที่สุดโดยไม่เข้าไปเกี่ยวข้องอะไรเลย ฉันกำลังทดสอบ DW ของฉันโดยใช้ตาราง timeZone และ TimeZoneBridge คล้ายกับของคุณ นอกจากนี้ยังมีตาราง TimeDimension และ DateDimension ฉันสร้างดัชนีคลัสเตอร์บน date_key_local, time_key_local และ timezone_id ดังนั้นการแปลเวลาท้องถิ่นเป็นเวลา UTC โดยใช้ TimeZoneBridge น่าจะเร็ว
dsum

1
คีย์คลัสเตอร์หลักของเราสำหรับตารางบริดจ์อยู่ในคอลัมน์วันที่ / เวลา utc + รหัสเขตเวลา (ถ้าฉันจำได้อย่างถูกต้อง) เนื่องจากคีย์เวลาของตารางข้อเท็จจริงทั้งหมดจะอยู่ใน utc คุณจะเข้าร่วมบริดจ์ผ่าน utc keys + tz id อาจทำงานได้ดีกว่าถ้ามีดัชนีคลัสเตอร์อยู่ ทำสิ่งที่สมเหตุสมผลสำหรับความต้องการของคุณ ฉันดีใจที่คำตอบของฉันช่วยใครซักคนฉันคิดว่ามันเป็นวิธีการที่ดีและจากการทดสอบทั้งหมดของเรามันก็ยังเร็วพอสมควรระวังเมื่อมันมาถึง WHERE clause: กรองช่วงวันที่ที่คุณต้องการให้เร็วที่สุด เป็นไปได้ในแบบสอบถามของคุณ
แมตต์ Palmerlee

สิ่งนี้มีเพียงวันที่ทั้งหมดหรือไม่ หรือถ้าคุณมีค่า 86000 "วันที่ / เวลา" ในตารางข้อเท็จจริงของคุณตารางบริดจ์จะมี 86000 แถว * n โซนเวลาที่รองรับและนั่นเป็นเพียงวันเดียว
แอรอนเบอร์ทรานด์ด์

1
บางทีคุณสามารถเพิ่มคำจำกัดความของตารางที่แน่นอนที่คุณมีเพื่อให้ผู้อ่านสามารถเห็นข้อ จำกัด หลักที่ไม่ซ้ำกัน
ypercubeᵀᴹ

@AaronBertrand มันขึ้นอยู่กับธัญพืช (หรือ granularity ที่คุณเลือก) เพื่อติดตามข้อมูลของคุณในกรณีของเราเราต้องการเพียง 15 นาทีในตารางความเป็นจริงในตารางความเป็นจริงของเราดังนั้นมันจึงเป็นเพียง 4 * 24 = 96 บันทึกต่อวันต่อเขตเวลาที่เราต้องการ ซึ่งสมเหตุสมผลอย่างสมบูรณ์
Matt Palmerlee

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เขตร่วมกับตาราง 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)),
...
)

นี่คือความละเอียดครึ่งชั่วโมงดังนั้นจึงมี 48 บันทึกต่อวัน 350,400 ใน 20 ปี - จัดการค่อนข้าง

วันที่ / เวลาของกิจกรรมถูกแปลเป็น 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'

คุณอาจถูกล่อลวงให้ทำสิ่งต่าง ๆ ให้ง่ายขึ้นโดยแทนที่TimeZoneSKด้วยREALออฟเซ็ต (เช่น -5.0 สำหรับเวลาออมแสงตอนกลางของสหรัฐอเมริกา) แต่สิ่งนี้จะพังถ้าวันที่ / เวลาสำหรับบันทึกความจริงบางอย่างอยู่ในการปรับเวลาตามฤดูกาล

หากเหตุการณ์สำหรับบันทึกข้อเท็จจริงสามารถเกิดขึ้นได้ในเขตเวลาที่แตกต่างกันเช่นการจัดส่งหรือเที่ยวบินคุณต้องมีเขตเวลาในแต่ละวันและคุณมีความยาวไม่เกินห้าไบต์ต่อวัน


มันเป็นวิธีการที่สร้างสรรค์ อย่างไรก็ตามอย่างที่คุณบอกว่าคุณมีเพียง 350,400 แถวในตารางสลัว datetime ที่รวมกันของคุณหากคุณเริ่มเปลี่ยนเกรนเป็นความละเอียดปลีกย่อยคุณจะได้รับการบันทึกนับล้าน ๆ อย่างรวดเร็ว หากคุณเลือกที่จะมีมิติวันที่แยกจากมิติเวลาคุณมีเพียง 48 แถวในตารางมิติเวลาของคุณและเพียง 365 แถวต่อปีในตารางมิติวันที่ของคุณ (หรือ 7300 แถวใน 20 ปี) ตารางข้อเท็จจริงของคุณนั้นมีคอลัมน์สำหรับ date_key และ time_key สิ่งนี้ยังทำให้มีความยืดหยุ่นมากขึ้นถ้าคุณมีตารางข้อเท็จจริงบางอย่างที่ต้องการเพียงแค่วันที่แบบละเอียด
Matt Palmerlee

1
หนึ่งล้านแถวในมิติข้อมูลไม่เกี่ยวข้องกับฉัน - ข้อมูลจะเปลี่ยนแปลงเพียงครั้งเดียวในรอบทศวรรษและดัชนีครอบคลุมใน PK และเขตข้อมูลที่ใช้มากที่สุดสองหรือสามเขตจะใช้เซิร์ฟเวอร์ RAM จำนวนเล็กน้อย อย่างไรก็ตามการเพิ่มครึ่งโหลSMALLINTไปยังตารางข้อเท็จจริงพันล้านแถวคือ 12 GB บวกกับค่าใช้จ่ายและตอนนี้คุณกำลังพูดถึงเงินจริง สำหรับวันที่ต้องเก็บวันที่แน่นอนคุณสามารถชี้ให้พวกเขาไปยังบันทึก "12:00 AM" สำหรับวันที่ที่เหมาะสม
จอนแห่งการค้าขายทั้งหมด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.