圖解事實表、維度表與星形架構:數據中台讓資料一目瞭然的設計
事實表存數字與事件,維度表存看資料的角度,星形架構把它們組成最適合分析的模型。用小明買咖啡豆的一筆訂單,圖解數據中台為什麼能讓資料一目瞭然,以及它與正規化、反正規化的差別。
在上一篇文章中,我們聊到了資料庫的「正規化」與「反正規化」,以及資料管理員與資料取用者之間的兩難。
為了讓資料取用者不用再跨越五六張表找資料,數據中台的架構設計難道只能沿用正規化與反正規化?還是有更好的做法?
2025年我開始教 Power BI 的時候,接觸到了「事實表(Fact Table)」與「維度表(Dimension Table)」的設計。這讓我非常好奇:這跟傳統的正規化與反正規化又有什麼不同?
這篇文章,就讓我們來拆解這些讓資料分析師愛不釋手的魔法。
數據分析的兩大主角:事實表與維度表
1. 事實表(Fact Table):記錄「發生了什麼事」
事實表是分析模型中用來記錄「事件」或「數字指標」的表。它通常回答:發生了什麼事?發生在什麼時間?數量、金額、次數是多少?
簡單來說:事實表 = 業務事件 + 可衡量數字。
例如,小明 8 月 15 日在「台北信義店」買了 2 包咖啡豆,共 1,000 元——這筆訂單寫入「銷售事實表」會這樣呈現,包含業務計算需要加總計算的指標是「數量」與「金額」,而其他的 ID 則是拿來連到維度表的鑰匙(Key):
| order_id | date_id | customer_id | product_id | store_id | quantity | amount |
|---|---|---|---|---|---|---|
| O001 | 20260815 | C001 | P001 | S001 | 2 | 1000 |
表格裡的 ID 就是「鑰匙(Key)」的意思:兩張表只要共用同一個編號,就能接起來。拿著 customer_id = C001 到客戶維度表,找到編號相同的那一列,兩張表就對上了——像拿號碼牌領餐一樣,資料庫的 JOIN 做的就是這件事。
對照上面這一列:C001 查客戶維度表是小明、P001 查商品維度表是咖啡豆、S001 查門市維度表是台北信義店;quantity 是購買數量 2 包,amount 是總金額 1,000 元(2 包 × 單價 500 元)。
2. 維度表(Dimension Table):描述「事件的背景」
維度表是用來描述事實的背景資料。它通常回答:這是誰?什麼商品?哪一天?哪個地點?
簡單來說:維度表 = 看資料的角度。
例如:
- 客戶維度表: 告訴我們客戶的名字、性別、城市、會員等級。(C001 → 小明:台北、金卡會員)
- 商品維度表: 告訴我們商品的名稱、類別、品牌。(P001 → 咖啡豆,食品類)
- 日期維度表: 告訴我們某個日期對應的年份、月份、星期幾。(20260815 → 2026 年 8 月、星期六)
其中「日期維度」最常讓人疑惑:日期本身不就是資訊了嗎,為什麼還要一張表?因為分析常用的「年、季、月、星期幾、是否假日」,如果每次都讓每個人自己從日期推算,算法可能不一樣——光「第幾季」就有日曆年度和會計年度兩種算法。先算好、放進維度表,全公司查出來的答案就是同一個。
日期維度表實際長這樣(小明那筆 20260815 就落在第二列):
| date_id | 日期 | 年 | 月 | 星期幾 | 是否假日 |
|---|---|---|---|---|---|
| 20260814 | 2026-08-14 | 2026 | 8 | 星期五 | 否 |
| 20260815 | 2026-08-15 | 2026 | 8 | 星期六 | 是 |
| 20270101 | 2027-01-01 | 2027 | 1 | 星期五 | 是(元旦) |
所以像「假日銷售 vs 平日銷售」這種分析,JOIN 這張表就有現成的「是否假日」欄位,不用每次現場寫判斷式。
當你想要問:「今年每個城市的銷售金額是多少?」
你的資料來源就會是:
- 銷售金額: 來自「事實表」。(O001 的 1,000 元)
- 今年: 來自「日期維度」。(20260815 → 2026 年)
- 城市: 來自「客戶維度」或「門市維度」。(C001 → 小明住台北)
以小明那筆訂單來說:事實表拿出 1,000 元、日期維度認出「2026 年」、客戶維度認出「台北」——三個來源拼出答案的一列:2026 年・台北・1,000 元。

什麼是「星形架構」?
星形架構(Star Schema)就是中間擺一張「事實表」,周圍連接著多張「維度表」。因為它的關聯圖看起來就像一顆星星,因而得名。

等一下,事實表跟上一篇的「訂單明細表」是不是很像?
眼尖的你可能發現了:事實表裡也是一堆 ID 加上數量與金額,跟上一篇正規化拆出來的「訂單明細表」幾乎長得一模一樣,差別在哪?
先看正規化這邊。線上系統為了記錄交易細節,把小明這筆訂單拆成兩張表,並且記錄了單價與狀態:
表一:orders (訂單主檔)
記錄這筆訂單是「誰、在什麼時候、哪家店」買的,以及「有沒有付款」。
| order_id | order_date | customer_id | store_id | status |
|---|---|---|---|---|
| O001 | 2026-08-15 | C001 | S001 | paid |
表二:order_items (訂單明細)
記錄這筆訂單「買了什麼、買幾個、當時單價多少」。
| order_id | product_id | quantity | unit_price |
|---|---|---|---|
| O001 | P001 | 2 | 500 |
注意:這兩張表裡都沒有「城市」。S001 是哪個城市的店、小明住在哪個城市,要再連到「門市表」與「客戶表」才查得到——這就是待會對照表裡「繼續拆下去」的意思。
同一筆訂單,到了星形架構的事實表長這樣——金額已經算好(2 包 × 500 元 = 1,000 元),而且只留下已付款的訂單:
| order_id | date_id | customer_id | product_id | store_id | quantity | amount |
|---|---|---|---|---|---|---|
| O001 | 20260815 | C001 | P001 | S001 | 2 | 1000 |
這樣設計的巨大優勢:團隊用 BI 拉資料時,再也不用去碰原始的 orders 和 order_items,不用自己過濾出已付款(paid)的訂單,也不用擔心數量乘錯單價——因為數據中台的加工流程(實務上常用 dbt 這類工具)已經幫大家把資料「清洗乾淨、算出金額、並附上所有的維度鑰匙」了!
| 正規化的訂單明細表 | 星形架構的事實表 | |
|---|---|---|
| 為誰設計 | 系統寫入用:一筆一筆新增、修改 | 分析讀取用:整批加總、換角度切 |
| 資料進去之後 | 會隨狀態更新(訂單改了就改) | 不再改動,事件一筆一筆往後追加 |
| 連出去的表 | 繼續拆下去(客戶表再連到城市表) | 維度表刻意合成寬表,查詢一步到位 |

真正的差別在兩張表身處的世界。正規化的世界裡,訂單明細表連出去的每張表都會繼續拆,想查「小明在哪個城市買的」,要一路 JOIN 三張表;星形架構的世界裡,維度表刻意反正規化成寬表,城市、區域通通放進客戶維度,查詢一步到位。
等等,維度表這樣「合」,不會踩到上一篇說的反正規化的坑(資料重複、要自己維護一致性)嗎?會,但代價可控:維度表通常不大(幾千個客戶,對比幾百萬筆交易),而且由中台統一維護一份,不是讓每個報表各自合表、各自出錯——這正是把「合」放到對的位置的意思。
所以星形架構不是第三種新魔法,而是把上一篇的兩難各放到對的位置:中間的事實表保持「拆」的細緻——每筆事件只存一次;四周的維度表選擇「合」的方便——描述資料一張裝齊。
這也正面回答了開頭的問題:數據中台不必在正規化與反正規化之間二選一。
數據中台的分層設計:五層架構
那實務上,資料會直接從來源系統一步跳進星形架構嗎?不會。一個成熟的數據中台,會把資料分層加工,每一層只負責一件事:

stage_原始保留層: 保留來源系統的資料原貌(如原始訂單 O001,狀態欄還是原始的 paid)。int_標準化層: 統一語意與規則,讓全公司說同一種話(例如把狀態 paid 統一成「已付款」)。dim_維度層: 存放看資料的角度(如dim_customer:小明、台北、金卡)。fact_事實層: 存放訂單事件與金額,並連動維度的 Key(如fact_sales:O001,2 包、1,000 元)。mart_應用市集層: 提供給報表、API、AI 靈活使用的寬表或資料產品(如「城市 × 月份銷售」寬表)。
細心的你可能注意到:上一篇聊的「快照」去哪了?快照進了中台之後要怎麼設計——歷史版本怎麼留、每天的狀態怎麼存——資訊量值得專文一篇,我們另開一篇好好講。
一句話總結:這些名詞到底差在哪?
這套「事實表+維度表」的家,傳統上叫 資料倉儲(Data Warehouse);數據中台則是在資料倉儲的基礎上,把資料當成全公司共用的產品來經營的一整套做法。本文談的模型設計兩者通用,所以下表把它們寫在一起。
| 名稱 | 它在回答什麼? | 常見位置 | 特性 |
|---|---|---|---|
| 正規化 | 資料要不要拆乾淨? | 線上交易系統 (OLTP) | 減少重複,重視一致性 |
| 反正規化 | 資料要不要合起來方便查? | 報表層、Mart、寬表 | 查詢方便,可能有重複 |
| 事實表 | 發生了什麼?數字是多少? | 資料倉儲/ 數據中台 | 存事件與指標 |
| 維度表 | 從哪些角度分析? | 資料倉儲/ 數據中台 | 存描述與分類 |
| 星形架構 | 事實與維度怎麼組? | BI、資料倉儲分析層 | 好查詢、好理解、好做報表 |
💡 核心觀念:
現在我們知道星形架構很適合做報表,但一定有人會問:「我直接從現在的線上系統撈資料不行嗎?為什麼要這麼麻煩再建一套數據中台和星形架構?」下一篇,我們再來分析這件事情。
延伸閱讀
如果你也走在自己的路上,歡迎訂閱《小穗步電子報》——我會把每一次的覺察與練習,寫成信寄給你。→ 訂閱小穗步電子報