讓 Cosmos DB 的資料開口說話:從等分析師,到自然語言查詢|專家論點【黃婉中】
作者:黃婉中(雲端架構師)
有個貸款客戶想要回答一些商業問題,例如「這個月哪個合作機構的成交量最高」。他們本來是用 Cosmos DB 存資料,但每次想知道這類問題的答案,都得找分析師,寫一段查詢、等結果。為了縮短等待,我們幫他們把資料攤平、做反正規化,讓客戶從此可以直接用自然語言去查詢,不用再等分析師。

這篇想把中間比較細節的兩個部分拆開來講:一是為什麼 Cosmos DB 不適合直接分析,二是攤平跟反正規化在做什麼。
資料庫的兩種個性:OLTP 跟 OLAP
先講兩個詞,因為後面會一直用到。
OLTP(Online Transaction Processing,線上交易處理):例如打給客服、銀行轉帳。OLTP 資料庫的強項是「單一一筆」存取。
OLAP(Online Analytical Processing,線上分析處理):例如「這個月哪個放款機構成交最多」。OLAP 資料庫的強項是「大量資料」統計。
「AI履歷健檢」看見自己優勢:https://campaign.1111.com.tw/resume-review/
更多科技工作請上科技專區:https://techplus.1111.com.tw/
Cosmos DB 是 OLTP,但跟 SQL 的 OLTP 不一樣
這裡有個容易搞混的地方:傳統 SQL 資料庫也是拿來做 OLTP 的,但它跟 Cosmos DB 做 OLTP 的方式不一樣。
SQL 資料庫:把資料拆細(正規化)。 客戶資料一張表、貸款資料一張表、還款紀錄一張表,彼此用關聯串起來。這樣做的好處是,如果客戶改名字,只要改一個地方,不會有些表改了、有些表忘記改,資料不會兜不起來。查詢的時候,用 JOIN 把幾張表接起來看。
Cosmos DB:把資料打包在一起。 一個客戶的姓名、聯絡方式、名下所有貸款、每筆貸款的還款紀錄,全部塞進同一份 JSON 文件裡。客服系統一查這個客戶,一次就把所有相關資料抓齊,不用像 SQL 那樣東拼西湊做 JOIN,速度極快。
這也是為什麼 Cosmos DB 裡的資料長得「一層包一層」,技術上叫巢狀結構(nested structure),客戶底下包貸款,貸款底下包還款紀錄,像俄羅斯娃娃一樣。是為了讓應用程式查詢快的刻意設計。
兩個產品都是為了讓「單筆存取」快,只是方法不同。
想做分析,才發現這個設計不夠用
當資料累積多了,客戶開始想要做分析,回答「這個月哪個放款機構成交最多」。像這種要攤開所有客戶、所有貸款,跨資料去加總比較,是巢狀打包結構最不擅長的事。因為資料被鎖在一份一份的文件裡,每份都要打開來看,才能湊出跨資料的統計結果。
解法:「反正規化」把資料變成一張寬表
要解決這個問題,做法是把巢狀資料攤平成表格。
用一個具體例子說明。一間店有兩個客戶:小明住台北,買過兩次東西;小華住高雄,買過一次。
如果是 SQL 正規化的做法,會拆成三張小表:
客戶表
| 客戶編號 | 姓名 | 城市 |
| C001 | 小明 | 台北 |
| C002 | 小華 | 高雄 |
產品表
| 產品編號 | 產品名稱 | 單價 |
| P01 | 鍵盤 | 100 |
| P02 | 滑鼠 | 200 |
訂單表
| 訂單編號 | 客戶編號 | 產品編號 | 日期 | 數量 |
| O1001 | C001 | P01 | 7/26 | 1 |
| O1002 | C001 | P02 | 7/28 | 2 |
| O1003 | C002 | P02 | 7/27 | 1 |
「小明」這兩個字只在客戶表裡出現過一次,訂單表只存客戶編號,不存名字。這樣做的好處是,小明改名字只要改一個地方;但想知道「小明總共花了多少錢」,得把三張表 JOIN 起來,先查出客戶編號、再對應產品單價,才能算出總金額。
如果是 OLAP 反正規化的做法,會攤平成一張寬表:
銷售事實表
| 客戶姓名 | 城市 | 產品名稱 | 單價 | 日期 | 數量 | 小計 |
| 小明 | 台北 | 鍵盤 | 100 | 7/26 | 1 | 100 |
| 小明 | 台北 | 滑鼠 | 200 | 7/28 | 2 | 400 |
| 小華 | 高雄 | 滑鼠 | 200 | 7/27 | 1 | 200 |
「小明」「台北」這些資訊重複出現了兩次。在正規化的世界裡,這種重複是大忌;但在這裡是刻意設計的,因為現在想問「小明總共花了多少錢」,不用 JOIN 任何表,直接把小明那幾列的「小計」加起來就好;想問「哪個城市買最多」,把「城市」欄位拿出來加總分組就好。
這種「一列代表一筆事件、允許重複」的表,在資料倉儲的世界裡叫 fact table(事實表);像「小明」「台北」這種會重複、用來描述這筆事件的欄位,叫 dimension(維度)。
一句話總結兩者的差異:正規化把「小明」這個名字存一次、用編號互相參照,換取修改資料時的安全;反正規化把「小明」這個名字允許重複貼在每一列上,換取統計加總時不用東拼西湊查好幾張表。
這裡說的「攤平」,就是反正規化,把 Cosmos DB 裡打包好的巢狀資料,拆開重組成扁平的寬表。欄位命名清楚、預先算好常用的加總。讓後面不管是人還是 AI,都能一眼看懂、快速查詢。
下篇想接著聊:整理完的資料放好之後,該用什麼工具讓業務人員自然語言查詢,這件事該自己組一套系統,還是買現成的整合服務。
![]()





