與其使用嚴格的 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_pct
參數相比,innodb_old_blocks_time
參數的效果更難以預測,相對較小,並且會隨著工作負載而變化。如果調整 innodb_old_blocks_pct
所帶來的效能提升不足,請進行您自己的基準測試以得出最佳值。