一:插入緩沖
二:二次寫
三:自適應哈希
四:預讀
1.插入緩沖(insert buffer)
插入緩沖(Insert Buffer/Change Buffer):提升插入性能,change buffering是insert buffer的加強,insert buffer只針對insert有效,change buffering對insert、delete、update(delete+insert)、purge都有效
只對於非聚集索引(非唯一)的插入和更新有效,對於每一次的插入不是寫到索引頁中,而是先判斷插入的非聚集索引頁是否在緩沖池中,如果在則直接插入;若不在,則先放到Insert Buffer 中,再按照一定的頻率進行合並操作,再寫回disk。這樣通常能將多個插入合並到一個操作中,目的還是為了減少隨機IO帶來性能損耗。
使用插入緩沖的條件:
* 非聚集索引
* 非唯一索引
Change buffer是作為buffer pool中的一部分存在。Innodb_change_buffering參數緩存所對應的操作:(update會被認為是delete+insert)
innodb_change_buffering,設置的值有:inserts、deletes、purges、changes(inserts和deletes)、all(默認)、none。
all: 默認值,緩存insert, delete, purges操作
none: 不緩存
inserts: 緩存insert操作
deletes: 緩存delete操作
changes: 緩存insert和delete操作
purges: 緩存后台執行的物理刪除操作
可以通過參數控制其使用的大小:
innodb_change_buffer_max_size,默認是25%,即緩沖池的1/4。最大可設置為50%。當MySQL實例中有大量的修改操作時,要考慮增大innodb_change_buffer_max_size
上面提過在一定頻率下進行合並,那所謂的頻率是什么條件?
1)輔助索引頁被讀取到緩沖池中。正常的select先檢查Insert Buffer是否有該非聚集索引頁存在,若有則合並插入。
2)輔助索引頁沒有可用空間。空間小於1/32頁的大小,則會強制合並操作。
3)Master Thread 每秒和每10秒的合並操作。
2.二次寫(double write)
Doublewrite緩存是位於系統表空間的存儲區域,用來緩存InnoDB的數據頁從innodb buffer pool中flush之后並寫入到數據文件之前,所以當操作系統或者數據庫進程在數據頁寫磁盤的過程中崩潰,Innodb可以在doublewrite緩存中找到數據頁的備份而用來執行crash恢復。數據頁寫入到doublewrite緩存的動作所需要的IO消耗要小於寫入到數據文件的消耗,因為此寫入操作會以一次大的連續塊的方式寫入
在應用(apply)重做日志前,用戶需要一個頁的副本,當寫入失效發生時,先通過頁的副本來還原該頁,再進行重做,這就是double write
doublewrite組成:
內存中的doublewrite buffer,大小2M。
物理磁盤上共享表空間中連續的128個頁,即2個區(extend),大小同樣為2M。
對緩沖池的臟頁進行刷新時,不是直接寫磁盤,而是會通過memcpy()函數將臟頁先復制到內存中的doublewrite buffer,之后通過doublewrite 再分兩次,每次1M順序地寫入共享表空間的物理磁盤上,在這個過程中,因為doublewrite頁是連續的,因此這個過程是順序寫的,開銷並不是很大。在完成doublewrite頁的寫入后,再將doublewrite buffer 中的頁寫入各個 表空間文件中,此時的寫入則是離散的。如果操作系統在將頁寫入磁盤的過程中發生了崩潰,在恢復過程中,innodb可以從共享表空間中的doublewrite中找到該頁的一個副本,將其復制到表空間文件,再應用重做日志。
3.自適應哈希索引(ahi)
Adaptive Hash index屬性使得InnoDB更像是內存數據庫。該屬性通過innodb_adapitve_hash_index開啟,也可以通過—skip-innodb_adaptive_hash_index參數
關閉
Innodb存儲引擎會監控對表上二級索引的查找,如果發現某二級索引被頻繁訪問,二級索引成為熱數據,建立哈希索引可以帶來速度的提升
經常訪問的二級索引數據會自動被生成到hash索引里面去(最近連續被訪問三次的數據),自適應哈希索引通過緩沖池的B+樹構造而來,因此建立的速度很快。
哈希(hash)是一種非常快的等值查找方法,在一般情況下這種查找的時間復雜度為O(1),即一般僅需要一次查找就能定位數據。而B+樹的查找次數,取決於B+樹的高度,在生產環境中,B+樹的高度一般3-4層,故需要3-4次的查詢。
innodb會監控對表上個索引頁的查詢。如果觀察到建立哈希索引可以帶來速度提升,則自動建立哈希索引,稱之為自適應哈希索引(Adaptive Hash Index,AHI)。
AHI有一個要求,就是對這個頁的連續訪問模式必須是一樣的。
例如對於(a,b)訪問模式情況:
where a = xxx
where a = xxx and b = xxx
特點
1、無序,沒有樹高
2、降低對二級索引樹的頻繁訪問資源,索引樹高<=4,訪問索引:訪問樹、根節點、葉子節點
3、自適應
3、缺陷
1、hash自適應索引會占用innodb buffer pool;
2、自適應hash索引只適合搜索等值的查詢,如select * from table where index_col='xxx',而對於其他查找類型,如范圍查找,是不能使用的;
3、極端情況下,自適應hash索引才有比較大的意義,可以降低邏輯讀。
4.預讀(read ahead)
InnoDB使用兩種預讀算法來提高I/O性能:線性預讀(linear read-ahead)和隨機預讀(randomread-ahead)
為了區分這兩種預讀的方式,我們可以把線性預讀放到以extent為單位,而隨機預讀放到以extent中的page為單位。線性預讀着眼於將下一個extent提前讀取到buffer pool中,而隨機預讀着眼於將當前extent中的剩余的page提前讀取到buffer pool中。
線性預讀(linear read-ahead)
方式有一個很重要的變量控制是否將下一個extent預讀到buffer pool中,通過使用配置參數innodb_read_ahead_threshold,可以控制Innodb執行預讀操作的時間。如果一個extent中的被順序讀取的page超過或者等於該參數變量時,Innodb將會異步的將下一個extent讀取到buffer pool中,innodb_read_ahead_threshold可以設置為0-64的任何值,默認值為56,值越高,訪問模式檢查越嚴格
例如,如果將值設置為48,則InnoDB只有在順序訪問當前extent中的48個pages時才觸發線性預讀請求,將下一個extent讀到內存中。如果值為8,InnoDB觸發異步預讀,即使程序段中只有8頁被順序訪問。你可以在MySQL配置文件中設置此參數的值,或者使用SET GLOBAL需要該SUPER權限的命令動態更改該參數。
在沒有該變量之前,當訪問到extent的最后一個page的時候,Innodb會決定是否將下一個extent放入到buffer pool中。
隨機預讀(randomread-ahead)
隨機預讀方式則是表示當同一個extent中的一些page在buffer pool中發現時,Innodb會將該extent中的剩余page一並讀到buffer pool中,由於隨機預讀方式給Innodb code帶來了一些不必要的復雜性,同時在性能也存在不穩定性,在5.5中已經將這種預讀方式廢棄。要啟用此功能,請將配置變量設置innodb_random_read_ahead為ON。