關于Buffer
全部緩沖區構成一個緩沖池
緩沖池:
- 緩沖區管理跟蹤BmTrace區
- 記錄緩沖區被使用的狀況
- BMT_LIMIT項
- 緩沖區描述符BufferDestriptors區
- 每個緩沖區都要一個描述符
- NBUFFER+1個(0~NBUFFER)
- 多出的一個(第NBUFFER個)作為空閑緩沖區的鏈頭,把所有空閑緩沖區鏈到一個雙鏈表中
- 緩沖區
- 實際存儲數據的地方
- NBUFFER個
- 緩沖區索引哈希表
- 通過表的文件節點(RelFileNode)和磁盤塊(文件頁),快速搜索到緩沖指定文件頁的緩沖區,避免全池搜索
預取算法原理
前面已經分析過:
數據庫存儲結構:元組-文件頁-物理段-表
元組即一條記錄,文件頁(磁盤塊)是存儲和維護的最小單位
數據庫訪問對象的過程可以分為:從磁盤找找到這個對象所在的數據庫(文件頁)-把數據塊(文件頁)從磁盤讀到內存-從內存訪問數據。
在這個過程中,磁盤和內存的IO之間的操作是最耗時的,也是影響響應時間的主要因素。
對于單次請求,這個過程是順序執行的。
但是對于多次并發請求,仍然順序執行,結果就是:在對內存中的數據進行處理時,磁盤IO處于空閑;需要讀取新的數據時,磁盤IO又稱為影響響應時間的主要因素。
如果能在處理內存中的數據時,就預測要從磁盤請求數據塊的順序,并提前將其讀入內存,就能夠減少等待IO完成所花費的時間。
預讀算法實現
- 定義1:
BUF_READ_AHEAD_AREA
表示預讀區域大小,以塊為單位 - 定義2:
BUF_READ_AHEAD_THRESHOLD
表示預讀的閾值
實現過程:
當系統調用ReadBuffer存取數據庫中的一個數據頁時:
- 如果數據頁不是已在緩沖池中,則從文件讀這個數據頁到緩沖區
- 在讀入之后,返回給CPU之前:
統計以當前頁為邊界的某個區域(BUF_READ_AHEAD_AREA
)內順序讀取的情況
- 如果這個區域內最近被存取的數據頁是按塊號順序(升序或降序),并發生的次數達到一個閾值(
BUF_READ_AHEAD_THRESHOLD
) - 則按照這個順序預取當前頁前/后的一些連續頁
- 否則不預取
通過預取算法,使得系統存取這些頁是,它們已在緩沖區中;
同時通過分析算法實現過程,可以發現該算法盡量保證了預取的命中率;否則頻頻無法命中的預取只會浪費系統系能,造成負面影響。
預取算法對性能的影響
在一些測試資料中可以看到,PostgreSQL通過實現這種算法,比較大的降低了響應時間,但是吞吐量并不會收到明顯影響。
這是符合預期的:預取算法其實是通過減少系統空閑來提高性能,并不是在硬件性能上有突破性的優化。