前面幾頁的 B-Tree / LSM 都是為 OLTP(線上交易)調的:按鍵取少量列、低延遲隨機讀寫。但分析型負載 (OLAP) 剛好相反——掃幾兆列、只碰其中四五個欄、做聚合。存取模式一翻轉,最划算的擺法也跟著翻:不再「一列的欄位擺一起」,而是「一欄的值擺一起」。
🧠 Intuition
TIP
分析查詢通常是「幾兆列 × 只要 4~5 個欄」。按列儲存 (row-oriented) 為了那幾個欄得把整列(上百欄)從磁碟撈進來再丟掉九成——純浪費。欄式儲存 (column-oriented) 把同一欄的所有值連續存成一個檔,查詢只讀用到的那幾個欄檔,I/O 立刻少一個數量級。
- OLTP vs OLAP 的存取模式:OLTP 按鍵取少量記錄、隨機低延遲讀寫,服務終端使用者,看的是最新狀態;OLAP 掃大量列做聚合、批次匯入 (ETL),服務內部分析師,看的是歷史事件,資料量從 GB–TB 級跳到 TB–PB 級。
- 資料倉儲 (data warehouse):把各 OLTP 系統的資料抽出一份唯讀副本,透過 ETL (Extract–Transform–Load) 匯入,好處是能獨立於線上系統、專為分析存取模式最佳化(前面那些 OLTP 索引不擅長分析查詢)。
- 欄式的關鍵前提:每個欄檔裡的列必須排在相同順序——要重組第 k 列,就從每個欄檔各取第 k 筆。
⚖️ Tradeoffs
星狀 schema:事實表 + 維度表
- 資料倉儲常用星狀架構 (star schema):中央是事實表 (fact table),每列是一個事件(如一筆銷售),欄位含屬性(售價、成本)與指向維度表 (dimension table) 的外鍵。
- 維度表描述事件的 who / what / where / when(產品、商店、日期,連日期都常做成維度表以編入公共假日等資訊)。事實表居中、維度表環繞如星芒,故名。
- 事實表常有上百個欄;雪花架構 (snowflake schema) 把維度再拆子維度、更正規化,但星狀因對分析師更直觀而更常用。
欄壓縮:bitmap + run-length
- 同一欄的值高度重複,特別好壓。點陣圖編碼 (bitmap encoding):一個有 n 種相異值的欄,建 n 個點陣圖,每個點陣圖每一位對應一列。n 小時每列只花一位;n 大導致點陣圖稀疏,就再套遊程編碼 (run-length encoding) 壓。
- 剛好貼合倉儲查詢:
WHERE product_sk IN (30,68,69)→ 載入三張點陣圖做 bitwise OR;WHERE product_sk=31 AND store_sk=3→ 兩張點陣圖做 bitwise AND。 - 壓縮還讓資料更省記憶體→CPU 快取的頻寬:壓緊的欄資料能塞進 L1 快取、在緊密迴圈裡用 SIMD 指令直接對壓縮資料做位元運算——即向量化處理 (vectorized processing)。
排序副本:Vertica 讓每份副本排序不同
- 欄式仍可整體按某欄排序(必須整列一起排以維持欄間對應);管理員依常見查詢挑排序鍵(如先日期再產品),日期範圍查詢就只掃一小段。
- 排序也助壓縮:排序後第一排序鍵產生大量連續重複值,遊程編碼可壓到極小(幫助在第一排序鍵最顯著、往後遞減)。
- Vertica 更進一步:資料本來就要複製多份防故障,那就讓每份副本用不同排序,查詢時挑最適合的那份——類似按列儲存的多重次要索引,但欄式沒有指向他處的指標,只有含值的欄本身。
欄式的寫入困難 → 借 LSM 的招
- 壓縮+排序讓讀極快,卻讓寫很痛:壓過的欄無法像 B-Tree 就地更新,往排序表中間插一列得重寫所有欄檔。
- 解法借 LSM-tree:寫入先進記憶體的排序結構,累積後批次合併到磁碟上的欄檔。查詢得同時看磁碟欄資料與記憶體最新寫入,但查詢優化器對使用者隱藏這個區分——這正是 Vertica 的做法。
物化視圖與 data cube
- 物化視圖 (materialized view):把查詢結果實際寫一份到磁碟(相對於查詢時才展開的虛擬視圖)。底層資料一變就得更新、增加寫入成本,但在讀取密集的倉儲裡通常划算。
- 資料立方體 (data cube / OLAP cube) 是物化視圖的特例:按多個維度預先聚合。以日期 × 產品的二維表為例,每格是該組合的聚合值,沿列或欄加總得單維彙總。
- 取捨:cube 讓特定查詢極快,卻喪失查原始資料的彈性(若「售價」不是維度,就算不出「售價 > 100 的銷售佔比」)。所以多數倉儲盡量保留原始資料,只把 cube 當特定查詢的加速手段。
🔑 Takeaways
- 存取模式決定擺法:OLTP 按鍵取列 → 按列存;OLAP 掃列聚合 → 欄式存(同一欄連續存,只讀用到的欄檔)。
- 欄式的三個乘數效應環環相扣:只讀需要的欄省 I/O、欄壓縮 (bitmap + RLE) 再省一層、壓緊的資料還讓 SIMD 向量化吃滿 CPU 快取。
- 排序同時服務查詢與壓縮;Vertica 索性讓每份副本排序不同。寫入的痛用 LSM 式記憶體暫存 + 批次合併化解。
- data cube 拿預聚合換極速,代價是失去查原始資料的彈性——所以它是加速層,不是取代原始資料。
No notes yet — jot your takeaways or Q&A here.