數據庫緩沖池(Buffer Pool)


數據庫緩沖池(buffer pool)

InnoDB存儲引擎是以頁為單位來管理存儲空間的,我們進行的增刪改查操作其實本質上都是在訪問頁面(包括讀頁面、寫頁面、創建新頁面等操作)。而磁盤Ⅳ/o需要消耗的時間很多,而在內存中進行操作,效率則會高很多,為了能讓數據表或者索引中的數據隨時被我們所用,DBMS會申請占用內存來作為數據緩沖池,在真正訪問頁面之前,需要把在磁盤上的頁緩存到內存中的Buffer Pool之后才可以訪問。
這樣做的好處是可以讓磁盤活動最小化,從而減少與磁盤直接進行工/0 的時間。要知道,這種策略對提升sQL語句的查詢性能來說至關重要。如果索引的數據在緩沖池里,那么訪問的成本就會降低很多。

緩沖池VS查詢緩存

緩沖池和查詢緩存是一個東西嗎?不是。

1、緩沖池(Buffer Pool)

首先我們需要了解在InnoDB存儲引擎中,緩沖池都包括了哪些。
在InnoDB存儲引擎中有一部分數據會放到內存中,緩沖池則占了這部分內存的大部分,它用來存儲各種數據的緩存,如下圖所示:

從圖中,你能看到InnoDB緩沖池包括了數據頁、索引頁、插入緩沖、鎖信息、自適應Hash 和數據字典信息等。

緩存池的重要性:

對於使用InnoDB作為存儲引擎的表來說,不管是用於存儲用戶數據的索引(包括聚簇索引和二級索引),還是各種系統數據,都是以的形式存放在表空間中的,而所謂的表空間只不過是InnoDB對文件系統上一個或幾個實際文件的抽象,也就是說我們的數據說到底還是存儲在磁盤上的。但是各位也都知道,磁盤的速度慢的跟烏龜一樣,怎么能配得上“快如風,疾如電"的CPU呢?這里,緩沖池可以幫助我們消除cPu和磁盤之間的鴻溝。所以InnoDB存儲引擎在處理客戶端的請求時,當需要訪問某個頁的數據時,就會把完整的頁的數據全部加載到內存中,也就是說即使我們只需要訪問一個頁的一條記錄,那也需要先把整個頁的數據加載到內存中。將整個頁加載到內存中后就可以進行讀寫訪問了,在進行完讀寫訪問之后並不着急把該頁對應的內存空間釋放掉,而是將其緩存起來,這樣將來有請求再次訪問該頁面時,就可以省去磁盤IO的開銷了。

緩存原則

“位置*頻次”這個原則,可以幫我們對I/o 訪問效率進行優化。
首先,位置決定效率,提供緩沖池就是為了在內存中可以直接訪問數據。
其次,頻次決定優先級順序。因為緩沖池的大小是有限的,比如磁盤有200G,但是內存只有16G,緩沖池大小只有1G,就無法將所有數據都加載到緩沖池里,這時就涉及到優先級順序,會優先對使用頻次高的熱數據進行加載

緩沖池的預讀特性

了解了緩沖池的作用之后,我們還需要了解緩沖池的另一個特性:預讀
緩沖池的作用就是提升I/o效率,而我們進行讀取數據的時候存在一個“局部性原理”,也就是說我們使用了一些數據,大概率還會使用它周圍的一些數據,因此采用“預讀"的機制提前加載,可以減少未來可能的磁盤Ⅳ/O操作。

緩沖池如何讀取數據

緩沖池管理器會盡量將經常使用的數據保存起來,在數據庫進行頁面讀操作的時候,首先會判斷該頁面是否在緩沖池中,如果存在就直接讀取,如果不存在,就會通過內存或磁盤將頁面存放到緩沖池中再進行讀取。

如果我們執行SQL語句的時候更新了緩存池中的數據,那么這些數據會馬上同步到磁盤上嗎?

實際上,當我們對數據庫中的記錄進行修改的時候,首先會修改緩沖池中頁里面的記錄信息,然后數據庫會以一定的頻率刷新到磁盤上。注意並不是每次發生更新操作,都會立刻進行磁盤回寫。緩沖池會采用一種叫做checkpoint的機制將數據回寫到磁盤上,這樣做的好處就是提升了數據庫的整體性能。
比如,當緩沖池不夠用時,需要釋放掉一些不常用的頁,此時就可以強行采用checkpoint的方式,將不常用的臟頁回寫到磁盤上,然后再從緩沖池中將這些頁釋放掉。這里臟頁(dirty page)指的是緩沖池中被修改過的頁,與磁盤上的數據頁不一致。

多個Buffer Pool實例

Buffer Pool本質是InnoDB向操作系統申請的一塊連續的內存空間,在多線程環境下,訪問Buffer Pool中的數據都需要加鎖處理。在Buffer Pool特別大而且多線程並發訪問特別高的情況下,單一的Buffer Pool可能會影響請求的處理速度。所以在Buffer Pool特別大的時候,我們可以把它們拆分成若干個小的Buffer Pool,每個Buffer Pool都稱為一個實例,它們都是獨立的,獨立的去申請內存空間,獨立的管理各種鏈表。所以在多線程並發訪問時並不會相互影響,從而提高並發處理能力。
我們可以在服務器啟動的時候通過設置innodb_buffer_pool_instances的值來修改Buffer Pool實例的個數比方說這樣:

[server]
innodb_buffer_pool_instances = 2

這樣就表面我們要創建2個buffer pool實例(緩沖池總量大小不變,即每個buffer pool的大小為原來的一半)

不過也不是說Buffer Pool實例創建的越多越好,分別管理各個Buffer Pool也是需要性能開銷的,InnoDB規定:當innodb_buffer_pool_sie的值小於1G的時候設置多個實例是無效的,InnoDB會默認把
innodb_buffer_pool_instances的值修改為1。而我們鼓勵在Buffer Pool大於或等於1G的時候設置多個Buffer Pool實例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM