理解 Database Buffer Cache 內部運作是 SQL 調優與實例調優的基石。本文深入解析 Oracle 8i 引入的 Midpoint Insertion Strategy、Touch Count 熱度追蹤、Hot/Cold 區域劃分、隱藏參數、X$BH 熱塊識別,以及 64 位元架構下全庫快取的可行性分析。
| 版本 | 策略 | 特點 |
|---|---|---|
| Pre-8i | LRU List 推入頭部 | 新塊佔據 MRU 端,大掃描易沖刷熱塊 |
| 8i+ | Midpoint Insertion | 新塊插入中點,需多次 Touch 才升級到 Hot 區 |
TCH 計數器。TCH++(受 _db_aging_touch_time 節流,預設 3 秒內重複存取不重複計數)。TCH > _db_aging_hot_criteria(預設 10)時,塊從 Cold 區移動到 Hot 區(MRU 端)。_db_percent_hot_default (預設 50%)_db_percent_hot_keep_db_percent_hot_recycle警告:隱藏參數僅供 Oracle Support 指導下調整,錯誤設定會導致 Cache 效率劇降甚至實例不穩定。
COL object FORMAT A30
COL file# FORMAT 9999
COL block# FORMAT 999999
COL touches FORMAT 999999
SELECT
o.object_name AS object,
bh.dbarfil AS file#,
bh.dbablk AS block#,
bh.tch AS touches
FROM x$bh bh
JOIN dba_objects o ON bh.obj = o.object_id
WHERE bh.tch > 10
ORDER BY bh.tch DESC;
結果解讀:TCH 高的物件為熱門存取對象,候選移入 KEEP Pool(DB_KEEP_CACHE_SIZE)長期駐留,避免被大掃描沖刷。
| Pool | 參數 | 適用對象 | 特性 |
|---|---|---|---|
| DEFAULT | DB_CACHE_SIZE | 一般物件 | Midpoint Insertion、Hot/Cold 雙區 |
| KEEP | DB_KEEP_CACHE_SIZE | 小型熱門表、索引、字典表 | 不淘汰、常駐記憶體 |
| RECYCLE | DB_RECYCLE_CACHE_SIZE | 大掃描表、臨時表、歷史分區 | 快速淘汰、不污染 DEFAULT |
-- 將熱門表指派到 KEEP Pool
ALTER TABLE hot_table STORAGE (BUFFER_POOL KEEP);
ALTER INDEX hot_idx REBUILD STORAGE (BUFFER_POOL KEEP);
64 位元定址 + 記憶體價格下降,使得 完全快取中小型資料庫 成為現實:
SELECT SUM(blocks) FROM dba_data_files; -- 配置總塊數
SELECT SUM(blocks) FROM dba_extents; -- 實際使用塊數
已用塊數 × DB_BLOCK_SIZE(含索引、系統表空間、Undo、Temp)。DB_CACHE_SIZE ≥ 實際需求 + 20% 預留。-- 預熱腳本範例
BEGIN
FOR r IN (SELECT owner, table_name FROM dba_tables WHERE owner NOT IN ('SYS','SYSTEM')) LOOP
EXECUTE IMMEDIATE 'SELECT /*+ FULL(t) */ COUNT(*) FROM '||r.owner||'.'||r.table_name||' t';
END LOOP;
END;
/
SELECT * FROM v$db_cache_advice、Buffer Cache Hit Ratio > 99%。DB_CACHE_SIZE 或啟用 KEEP/RECYCLE 分離。PHYSICAL READS 高、DB FILE SCATTERED READ 等待多 → 檢查大掃描是否可加索引/分區裁剪/並行查詢。BUFFER BUSY WAITS 多 → 熱塊競爭,考慮 PCTFREE、INITRANS、Reverse Key Index、Hash Partition。FREE BUFFER WAITS 多 → DBWR 寫入跟不上,增加 DB_WRITER_PROCESSES、檢查儲存 IOPS、啟用 Async I/O。Buffer Cache 不是越大越好:超過作業系統可用記憶體會觸發 Swapping,導致災難性效能崩塌。
黃金法則:盡可能大、但絕不 Swap。定期跑DB_CACHE_ADVICE找最佳平衡點。