藍圖
資料庫自己管理磁碟資料和緩衝區,而不是透過作業系統管理(Os is not your friend.)。
資料儲存
三層檢視
資料庫以頁(page)為儲存資料的基本單位,檔案(file)是一系列頁的集合,頁中儲存頁資料(data),形成檔案-頁-資料三層架構。
檔案有不同的組織形式,頁包含頁頭和頁資料,頁資料可以採用不同方式組織:元組,日誌,索引。
黃色部分為課程會提及的內容。
採用Heapfile進行檔案儲存時的執行圖:
- 頁目錄:儲存管理的頁的元資訊(空閒頁,空頁)
- 頁頭:儲存頁的元資訊(頁大小,校驗和,資料庫版本,事務可見性,壓縮後設資料)
面向元組的資料儲存
-
透過<FileId, PageId, Slot>定位到一個指向tuple的指標(磁碟地址),然後找到tuple。
-
slot指標的靈活性:內部元組位置變化時,外部無感知;指標可以指向其他頁,可以儲存大資料(檔案,大文字);支援變長記錄。
-
資料庫會為每個元組分配一個資料記錄的唯一標識(record identifier),來表示元組的物理位置。SQLite和Oracle中為ROWID,Pg中是CTID,<PageId, Slot>。但是他們對於應用程式是無用的。
-
Header包含:可見性資訊;NULL Bit Map。
-
Data包含:行資料。
Tuple只是一個字串(char[]),本身不儲存型別資訊,型別資訊存在資料庫的System Catalogs中。(為了保證資料緊湊;非自解釋的)
存資料時會遇到的問題:
- 資料對齊:填充,重排序
- 精確值問題:BIGDECIMAL(轉為字串儲存)
-
空值:Bit Map;特殊值
-
大值和檔案:Overflow Page和External File。
大值採用溢位頁;大檔案可以採用溢位頁,也可以用外部檔案系統儲存,然後儲存一個指向檔案路徑的指標,而不是直接儲存檔案內容(Oracle:BFILE, Microsoft: FILESTREAM)。
日誌結構儲存
基本概念:
- 利寫不利讀,非原地更新:只有PUT和DELETE操作,順序IO。查詢時由最新到最老時查詢日誌。
- 加速查詢:索引。
- 加速查詢:日誌壓縮,且壓縮時會排序日誌。
- 壓縮方式:層級壓縮,統一壓縮
特點 | Level Compaction | Universal Compaction |
---|---|---|
層級結構 | 有多層級,L0、L1、L2 等 | 無層級結構,所有檔案在同一級別 |
檔案組織方式 | 每個層級內檔案不重疊,跨層逐漸下推 | 基於檔案大小和數量合併,檔案可能有重疊 |
合併策略 | 層級壓縮,按順序下推合併 | 檔案數量和大小超過閾值時觸發合併 |
寫放大 | 較高,因為需要不斷下推檔案至更低層級 | 較低,因為減少頻繁合併 |
讀放大 | 較低,因為相同鍵在每層只存在一次 | 較高,因為沒有嚴格層級,需檢查多個檔案 |
適用場景 | 讀多寫少的場景 | 寫多讀少、實時資料的高寫入場景 |
索引組織儲存
直接用索引組織資料,資料掛在葉子結點上,Page內部的tuple有序。
SQLite和MySQL預設用這種方式組織資料,Oracle和SQL Server可選。
和基於元組的儲存對比:
特性 | Index-Organized Storage | Tuple-Oriented Storage |
---|---|---|
資料與索引儲存 | 資料儲存在主鍵索引結構中 | 資料和索引獨立儲存 |
資料排序 | 資料按照主鍵順序排序 | 資料無序儲存 |
主鍵查詢效能 | 高效,因資料已按主鍵排序 | 依賴主鍵索引,但資料本身無序 |
插入和更新效能 | 插入和更新時可能需要索引重排,較慢 | 插入和更新較快,無需主鍵排序 |
適用場景 | 主鍵查詢頻繁,資料順序性強的場景 | 多種查詢模式,插入和更新頻繁的場景 |
資料模型
- N-ary Storage Model (NSM)
- Decomposition Storage Model (DSM)
- Hybrid Storage Model (PAX)
NSM
優點:操作一條完整記錄時快速。
缺點:操作一批記錄的某一個特定列的時候,非順序讀取,會有無效IO,且資料不好做壓縮。
DSM
優點:可以取到一批特定列;可以做資料壓縮。
缺點:在操作完整記錄的時候,需要分解查詢,得到結果後還需要再進行合併。
PAX
結合了NSM和DSM,既能一次處理一個完整記錄,也能在讀取一系列特定的屬性時順序讀取並避免過多的無用IO。
資料壓縮方式
目標:
-
壓縮結果為定長值(儲存定長資料)。
-
僅在需要時解壓縮,否則都採用壓縮形式處理資料。
-
必須是無損的。
常用的壓縮方式:字典壓縮。
維護字典對映,資料表中儲存對映值。結果定長,且可以支援範圍查詢。
字典對映的實現方式:陣列。【雜湊表不支援範圍查詢,B+樹記憶體消耗大】
記憶體緩衝區
基本介紹
一般是一個固定大小的Hash table,同時附帶一些後設資料:
- 髒頁標誌位
- Pin/引用計數
- 訪問控制資訊
- Lock/Latch
DBMS的緩衝區不採用作業系統的頁緩衝區,而是透過直接IO來讀取硬碟,自己管理緩衝區,目的是:
- 避免重複的頁複製
- 自定義替換策略
- 對IO更有掌控度
替換策略
目標:正確性,準確性,速度,後設資料開銷小
-
LRU
-
CLOCK:近似的LRU,開銷小,一個Page只需要維護一個bit
-
LRU-K:記錄最近K次的訪問時間(解決順序洪泛問題;可以再維護一個Hash表,記錄驅逐時間,避免新熱點頁由於缺乏歷史資訊一直被驅逐)
-
MySQL雙列表:近似的LRU-K
髒頁後臺定期寫回,無需考慮寫會髒頁的開銷。
快取最佳化
1. 多緩衝區:物件ID對映;雜湊對映。
2. 預取:順序掃描;索引掃描。
3. 掃描共享(同步掃描):減少掃描次數,避免快取顛簸;如何使得結果一致是個挑戰。
4. 旁路快取:不快取順序掃描結果或是臨時資料(join,sorting),也叫輕量掃描(Light Scans)。
總結:順序掃描時,需要預取(pre-fetch)。
- 結果進快取:LRK-K或近似的LRU-K
- 結果不進快取:旁路快取(放到一個臨時緩衝區)