簡體   English   中英

數據倉庫中的Fact表上是否需要Surrogate主鍵?

[英]Are Surrogate Primary Keys needed on a Fact table in a Data Warehouse?

當我問我們的數據庫設計者為什么我們的Fact表沒有PK時,我被告知表中沒有唯一標識記錄的列,即使選擇了所有列。 當我建議我們在這種情況下成為一個標識欄時,我被告知“我只是浪費空間而且不需要它。”

我的感覺是源系統中的每個表都應該有一個PK,即使它是一個標識列。 鑒於數據倉庫(DW)是來自其他系統的數據的接收者 - 如果無法綁定單個記錄,我將如何確保DW中的數據准確反映源系統中的數據? 如果你有一個失控的加載程序搞砸了數據並運行了一個星期,你將如何協調與實時事務源系統的差異與某種獨特的約束條件進行比較?

數據倉庫不一定是關系數據存儲,盡管您可以選擇將其設置為一個,因此關系定義不一定適用。

只有當您想要對需要唯一標識符的數據執行某些操作時才需要主鍵(例如,將其跟蹤到源,但這並不總是必需或必要,甚至可能無論如何); 數據倉庫中的數據通常可以以不需要主鍵的方式使用。 具體而言,您可能不需要區分行。 通常用於構建聚合值。

時間不是構建數據倉庫表所必需的維度。

它可能在心理上不舒服,浪費空間是一個微不足道的問題,但你的同事是正確的 - PK是沒有必要的。

您至少應該在事實表上有一個自然鍵,以便您可以識別行並將其與源進行協調,或者在必要時跟蹤更改。

在SQL Server上,標識列為您提供免費的代理鍵以及使用序列的其他系統(例如Oracle),它可以相當容易地添加。 代理事實表鍵可用於各種不同的原因。 一些可能的應用是:

  • 有些工具喜歡在事實表上使用數字鍵,最好是單調增加。 一個例子是MS SQL Server Analysis Services,它真的喜歡為用於填充度量值組的事實表提供數字,單調遞增的鍵。 這對增量負載尤其要求。

  • 如果您在事實表之間存在任何關系(例如,熟悉保險的人員的書面獲得的保費分類),那么合成密鑰在這里很有幫助。

  • 如果您的維度與事實表(例如ICD代碼)存在M:M關系,則事實表上的數字鍵可以簡化此操作。

  • 如果您對事務有任何自聯接要求(例如,某些事務正在對其他事務進行更正),那么合成密鑰將簡化這些事務的使用。

  • 如果您在數據倉庫中重復操作(即通過生成反轉並重新聲明該行來處理對事務數據的更改),那么您可以為同一個自然鍵設置多個事實表行。

否則,如果你沒有任何東西以1:M關系加入你的事實表,那么合成密鑰可能不會被用於任何東西。

標識類型列是一個“代理”鍵,用於替換您的“候選”鍵之一(簡單地放置)。 如果沒有它,則添加代理鍵列不會添加任何內容。 這需要候選人密鑰。

我一直認為表應該由最常見的查詢或性能命中者排序,因此表的聚簇索引應該與最困難或常見的查詢一致。

主鍵不一定是聚簇索引,所以我知道你可能想知道我在哪里,但我更關心的是聚簇索引而不是主鍵(說實話,它們通常是互相跟隨的)。

所以對我來說最初的問題不是“我應該在事實表上有代理主鍵嗎?” 但更像是“我應該在事實表上有聚集索引嗎?” 我認為答案是肯定的,你應該有一個(是的,在這個網站上有其他帖子報道這個問題,但我仍然認為這里值得一提,以防這是人們真正問的問題,盡管寫錯了)

有時你想要一個代理鍵,但我會衷心地建議代理不是表的聚集索引。 這樣做會使表格與無意義的代理鍵一致。 (通常人們將代理標識列添加到表中並使其成為主鍵,默認情況下也是聚簇索引)

那么要在哪些列上建立聚簇索引? 我個人喜歡事實表的日期,為此您可能會添加其他維度的FK以獲得唯一性,但這會增加大小並且可能不會提供任何好處,因為索引有用,必須引用相關維度(在密鑰生成的重要性順序)。

為了解決這個問題(以及我在這里回答這個問題的原因)我認為你應該添加一個代理,然后在日期鍵上創建聚集索引,然后是代理(按照該順序)。 我這樣做是因為單獨的日期不會產生一個獨特的行,而是添加代理意志。 這樣可以按日期排序數據,這有助於所有其他非聚集索引,並使聚簇索引大小合理。

此外,隨着數據的增長,您可能希望對其進行分區,在這種情況下,您將需要一個始終為日期的分區鍵。 使用日期作為鍵的主要部分構建聚簇索引可以使這更容易。 通過分區,您現在可以使用滑動窗口技術來存檔舊數據或加載。

沒有主鍵的數據庫表似乎是一個糟糕的設計選擇,並為不同類型的異常提供了大量空間,即如何刪除或更新此類表中的單個記錄?

你是對的 - 有點兒。 沒有主鍵,表不符合關系的最小定義。 成為一個不能允許重復行的關系是至關重要的。 數據倉庫設計中的表應該是關系型的,即使它們不是嚴格的正常形式。

因此,行中必須有一些列(或列集)用於唯一標識行。 但它不一定必須是代理鍵的標識列。

如果事實表沒有可以作為候選鍵的角色的列集,那么此DW中需要更多的維度表,並且事實表中需要更多列。

僅這個新的維度可能不是主鍵; 它可以與Fact Table中的現有列組合以創建候選鍵。

我同意你的看法。

“我被告知,即使所有列都被選中,表中也沒有唯一標識記錄的列。” - 正如我所理解的那樣,這似乎打破了關系數據庫的基本功能。

事實包括附加值加上維度的外鍵。 對於我所知道的每個維度模型來說,時間是一個明顯的維度。 如果不出意外,包含時間戳的復合鍵肯定會足夠獨特。

我想知道你的DBA是否對維度建模有很多了解。 這是一種與正常的關系,交易風格不同的思維方式。

如果事實表位於星型模式的中心,那么實際上存在候選鍵。 如果將事實表中的所有外鍵一起使用,則指向維表中的行的那些外鍵,即候選鍵。

將它聲明為主鍵可能沒什么好處。 它唯一能做的就是保護你免受惡意ETL過程的侵害。 運行倉庫的人可能手頭有ETL處理。

就索引和查詢速度而言,與使用面向OLTP的數據庫相比,這與星型模式完全不同。 經營倉庫的人也可以擁有這些。

在設計用於OLTP的數據庫時,擁有一個沒有主鍵的表是不明智的。 同樣的考慮因素不會延續到倉庫中。

使用維度代理鍵的組合作為事實表的主鍵在所有情況下都不起作用。 考慮存在三個維度a,b和c的情況。 在大多數設計中,我們通常有一個“未知”的維度行,假設我總是為此行指定-1的代理鍵。 我可以輕松地在我的事實表中有兩行,其中鍵a = n1,b = n2和c = -1,即重復鍵,因為這兩行沒有得到維度c的有效值,因此兩者都解析為未知行。

您在這里混淆了兩個問題 - 在事實表中標識唯一記錄,並跟蹤從源系統到事實表的記錄。

在后一種情況下,源系統中的單個記錄很可能具有多個事實表記錄。 想象一下源系統記錄,代表從一個帳戶到另一個帳戶的資金轉移。 可能有兩個事實表記錄來表示這一點,一個用於借記帳戶,一個用於貸記帳戶。 此外,可能存在多個事實記錄來表示源系統記錄在其生命周期中的不同點處的不同狀態。

對於事實表上的主鍵問題,實際上沒有“正確”的答案。 您可能需要(例如,單個記錄的標識可以在系統用戶之間輕松傳遞,或者單個記錄可以輕松刪除或更新)。 但是對於Oracle系統來說,ROWID可能會很好地做到這一點,只要它偶爾會發生變化並不重要。

實際上,維護單個合成密鑰的開銷很小,無論如何都可以這樣做。 您可以選擇不對其進行索引,因為索引將比列本身更大的資源使用者。

沒有每行的唯一標識符甚至比它看起來更糟糕。 當然,它是不穩定的,很容易無意中刪除一些行。

但表現也差得多。 每當您最終要求數據庫為EmployeeType = 'Manager' Employees獲取行時,您正在進行字符串比較。 標識符更快更好。

此外,存儲是便宜的,在這種情況下,我想如果那樣,對空間的影響將不到25個百分點 - 作為數據倉庫,您可能正在設計數TB的數據。

http://www.ralphkimball.com/html/controversies.html

寓言:

事實表的主鍵包含所有引用的維度外鍵。

事實:

事實表通常有10個或更多外鍵連接到維度表的主鍵。 但是,行唯一性通常只需要事實表的外鍵引用的子集。 大多數事實表都有一個主鍵,它由外鍵的連接/復合子集組成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM