相較於使用嚴格的 LRU 演算法,InnoDB
使用一種技術來最小化帶入 緩衝池 且永不再次存取之資料量。目標是要確保經常存取(「熱門」)的頁面保留在緩衝池中,即使 預讀 和 完整資料表掃描 帶入之後可能會或可能不會存取的新區塊亦然。
新讀取的區塊會插入到 LRU 清單的中間。所有新讀取的頁面都插入到預設情況下距離 LRU 清單尾端 3/8
的位置。當頁面在緩衝池中首次被存取時,它們會被移動到清單的前面(最近使用端的結尾)。因此,從未存取的頁面永遠不會到達 LRU 清單的前端,並且比使用嚴格的 LRU 方法更快「老化」。這種安排將 LRU 清單分成兩個區段,其中插入點下游的頁面被視為「舊的」,並且是 LRU 淘汰的理想犧牲者。
如需 InnoDB
緩衝池的內部運作方式和有關 LRU 演算法的詳細資訊,請參閱 第 17.5.1 節,「緩衝池」。
您可以控制 LRU 清單中的插入點,並選擇 InnoDB
是否將相同的最佳化應用於資料表或索引掃描帶入緩衝池的區塊。組態參數 innodb_old_blocks_pct
控制 LRU 清單中「舊」區塊的百分比。innodb_old_blocks_pct
的預設值為 37
,對應於原始的固定比率 3/8。值範圍為 5
(緩衝池中的新頁面老化速度非常快)到 95
(只有 5% 的緩衝池保留給熱門頁面,使得演算法接近於熟悉的 LRU 策略)。
為了避免預讀導致緩衝池被擾動的最佳化,可以避免由於資料表或索引掃描而引起的類似問題。在這些掃描中,資料頁面通常在快速連續存取幾次之後,就不會再被接觸。組態參數 innodb_old_blocks_time
指定在首次存取頁面之後的時間視窗(以毫秒為單位),在此期間,可以在不移動到 LRU 清單的前面(最近使用的結尾)的情況下存取頁面。innodb_old_blocks_time
的預設值為 1000
。增加此值會使越來越多的區塊更有可能從緩衝池中更快地老化。
innodb_old_blocks_pct
和 innodb_old_blocks_time
都可以使用 MySQL 選項檔案(my.cnf
或 my.ini
)指定,也可以在執行階段使用 SET GLOBAL
語法變更。在執行階段變更值需要有足夠權限才能設定全域系統變數。請參閱 第 7.1.9.1 節,「系統變數權限」。
為了幫助您評估設定這些參數的效果,SHOW ENGINE INNODB STATUS
陳述式會報告緩衝池統計資訊。詳細資訊請參閱使用 InnoDB 標準監控器監控緩衝池。
由於這些參數的效果會因您的硬體組態、資料和工作負載的細節而有很大差異,因此在任何對效能至關重要或生產環境中變更這些設定之前,請務必進行基準測試以驗證其有效性。
在混合工作負載中,大部分活動屬於 OLTP 類型,並定期執行批次報告查詢,導致大量掃描時,在批次執行期間設定 innodb_old_blocks_time
的值,可以幫助將正常工作負載的工作集保留在緩衝池中。
當掃描無法完全放入緩衝池的大型表格時,將 innodb_old_blocks_pct
設定為較小的值,可以防止僅讀取一次的資料佔用緩衝池的大部分。例如,設定 innodb_old_blocks_pct=5
將僅讀取一次的資料限制在緩衝池的 5%。
當掃描可放入記憶體的小型表格時,在緩衝池中移動頁面的額外開銷較少,因此您可以將 innodb_old_blocks_pct
保留為其預設值,甚至設定更高,例如 innodb_old_blocks_pct=50
。
innodb_old_blocks_time
參數的效果比 innodb_old_blocks_pct
參數更難以預測,相對較小,並且會隨工作負載而變化。若調整 innodb_old_blocks_pct
無法充分改善效能,請進行您自己的基準測試,以獲得最佳值。