国产成人精品亚洲777人妖,欧美日韩精品一区视频,最新亚洲国产,国产乱码精品一区二区亚洲

您的位置:首頁技術(shù)文章
文章詳情頁

MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)

瀏覽:252日期:2023-10-04 07:03:27
什么是insert buffer?

插入緩沖,也稱之為insert buffer,它是innodb存儲引擎的關(guān)鍵特性之一,我們經(jīng)常會理解插入緩沖時緩沖池的一個部分,這樣的理解是片面的,insert buffer的信息一部分在內(nèi)存中,另外一部分像數(shù)據(jù)頁一樣,存在于物理頁中。

在innodb中,我們知道,如果一個表有自增主鍵,那么對于這個表的默認(rèn)插入是非常快的,注意,這里的主鍵是自增的,如果不是自增的,那么這個插入將會變成隨機(jī)的,就可能帶來數(shù)據(jù)頁分裂的開銷,這樣,插入就不是順序的,就會變慢。還有一種情況,就是如果我們插入的id不是順序的,而是隨機(jī)的,那么即使有自增主鍵,那么插入的速度也不會特別快。

如果我們定義了一個表,包含一個主鍵和一個非聚集索引,如下:

create table t(a int auto_increment,b varchar(30),primary key(a),key (b));

當(dāng)我們按照主鍵a進(jìn)行插入的時候,對于非聚集索引,也就是常說的二級索引b,它的插入不是順序的,插入性能必然會下降。

Innodb存儲引擎針對這種情況,設(shè)計了Insert Buffer,對于非聚集索引的插入或者更新操作,不是每一次插入到索引頁中,而是先判斷插入的非聚集索引頁是否在緩沖池中,如果在,則直接插入,如果不在,則先放入一個insert buffer中,告訴數(shù)據(jù)庫這個非聚集的索引已經(jīng)插入到了葉子節(jié)點(diǎn),實際上并沒有插入,只是存放在另外一個位置,然后再以一定的頻率和情況進(jìn)行Insert buffer和輔助索引葉子節(jié)點(diǎn)合并操作。這種時候,經(jīng)常能將多條記錄的插入合并到一個操作中,這樣就大大提高了非聚集索引離散插入的性能。

insert buffer的觸發(fā)條件?

insert buffer需要滿足兩個條件才能被使用,第一,索引是輔助索引,也就是二級索引,第二,索引不是唯一的。當(dāng)滿足上述兩個條件的時候,就可以使用insert buffer,從而提高數(shù)據(jù)庫的插入操作性能。

這里需要注意,如果在程序進(jìn)行了大量操作的時候發(fā)生了MySQL數(shù)據(jù)庫的宕機(jī),那么肯定有大量的insert buffer沒有合并到實際的非聚集索引中去,恢復(fù)可能會造成很長的時間。

為什么不能是唯一索引?

之所以不支持唯一索引,是因為如果輔助索引是唯一索引,那么在插入時需要校驗唯一性,校驗唯一性的時候就會發(fā)生離散讀取,從而又增加了開銷,那么insert buffer得不償失。

我們可以通過show engine innodb status來查看insert buffer的使用情況,如下:

mysql--root@localhost:dms_alimetadata 20:35:24>>show engine innodb statusG-------------------------------------INSERT BUFFER AND ADAPTIVE HASH INDEX-------------------------------------Ibuf: size 1, free list len 0, seg size 2, 0 mergesmerged operations: insert 0, delete mark 0, delete 0discarded operations: insert 0, delete mark 0, delete 0

其中size代表了已經(jīng)合并記錄頁的數(shù)量,free list len代表了空閑列表的長度,seg size顯示了當(dāng)前insert buffer的大小為2*16KB

引入Change Buffer的概念

最新的MySQL5.7已經(jīng)支持change buffer,事實上,它在innodb 1.0.x版本已經(jīng)引入,這個change buffer 可以理解為insert buffer的升級,也就是對常見的DML語言都可以進(jìn)行緩沖,包含insert delete以及update,對應(yīng)的分別是insert buffer,delete buffer以及purge buffer。

當(dāng)然,change buffer的使用對象仍然是非唯一的輔助索引。

這里我們以update操作為例,update的過程可以拆分為兩個部分:

第一個部分是將記錄的delete_mask標(biāo)記為刪除,如果你不了解delete_mask,可以在4月9號的文章中去看。第二個部分是真正的將記錄刪除。

而delete buffer對應(yīng)的是update的第一個過程,purge buffer對應(yīng)的是第二個部分。

在innodb中,我們可以通過參數(shù)innodb_change_buffering來開啟buffer的各種選項,該參數(shù)可選的值為inserts,deletes,purges,changes,all,none等,其中inserts,deletes和purges就是前面討論過的情況,changes表示開啟inserts和deletes,all表示開啟所有,默認(rèn)的參數(shù)如下:

mysql--root@localhost:dms_alimetadata 21:13:37>>show variables like ’%buffering%’;+-------------------------+-------+| Variable_name | Value |+-------------------------+-------+| innodb_change_buffering | all |+-------------------------+-------+1 row in set (0.01 sec)

我們還可以通過innodb_change_buffer_max_size來控制change_buffer的最大使用內(nèi)存數(shù)量,該參數(shù)的默認(rèn)值是25,也就是1/4,示例如下:

mysql--root@localhost:dms_alimetadata 21:20:52>>show variables like ’%innodb_change_buffer_max_size%’;+-------------------------------+-------+| Variable_name | Value |+-------------------------------+-------+| innodb_change_buffer_max_size | 25 |+-------------------------------+-------+1 row in set (0.00 sec)

在上面的show engine innodb status命令的輸出結(jié)果中,顯示了merged operation和discarded operation,其中insert 表示insert buffer的操作次數(shù),delete mark表示delete buffer的操作次數(shù),而delete表示purge buffer的操作次數(shù),discarded operation表示當(dāng)change buffer發(fā)生merge時,表已經(jīng)被刪除,此時就無需進(jìn)行合并。

Insert Buffer的實現(xiàn)?

insert buffer的數(shù)據(jù)結(jié)構(gòu)是一棵B+樹,類似聚集索引一樣,全局只有一棵insert buffer B+樹,它負(fù)責(zé)對所有的表進(jìn)行insert buffer,而這棵B+樹放在共享表空間中,也就是ibdata1文件中,因此,試圖通過ibd文件恢復(fù)表數(shù)據(jù)的時候可能會出現(xiàn)check table失敗,原因是表的輔助索引中的數(shù)據(jù)可能還在insert buffer中,所以通過ibd文件恢復(fù)文件之后,還需要進(jìn)行repair table操作來重建表上的輔助索引。

insert buffer既然是一棵樹,那么必定有葉子節(jié)點(diǎn)和非葉子節(jié)點(diǎn),非葉子節(jié)點(diǎn)存放的是查詢的search key值,它的構(gòu)造如下:

+---------+------------+-------+| space | marker | Value |+---------+------------+-------+

這個結(jié)構(gòu)一共占用9個字節(jié),其中,space表示待插入的記錄所在的表的表空間id,這個id是每個表都要有的唯一的id,其中space占用4個字節(jié),marker占用1個字節(jié),用來兼容老版本的insert buffer,offset占用4個字節(jié),表示頁所在的偏移量。

輔助索引的插入過程?

當(dāng)一個輔助索引要插入到數(shù)據(jù)頁的時候,如果這個數(shù)據(jù)頁不在緩沖池中,那么innodb會根據(jù)規(guī)則構(gòu)造一個search key,接下來將這個記錄插入到insert buffer的B+樹里面去,插入的過程中,需要對這個記錄進(jìn)行一些構(gòu)造,最終插入的結(jié)果是類似下面這樣的一條記錄:

+---------+------------+-------+------------+------+-------+------+-------+| space | marker | Value | metadata | | | | |+---------+------------+-------+------------+------+-------+------+-------+

可以發(fā)現(xiàn),最后面多了一個metadata的字段和4個其他的字段,先來說說metadata的字段,它占用4個字節(jié),它用來排序每個記錄進(jìn)入insert buffer的順序,從第5列開始,就是實際插入記錄的各個字段的值了,因此和單純的數(shù)據(jù)記錄相比,insert buffer需要額外13個字節(jié)的開銷。

為了保證每次merge insert buffer成功,需要設(shè)置一個特殊的數(shù)據(jù)頁來標(biāo)記每個輔助索引頁的可用空間,這個數(shù)據(jù)頁的類型為insert buffer bitmap,這個頁可以追蹤很多輔助索引頁的可用空間。這里簡單了解一下,下面會解釋它的用法。

Merged Insert Buffer的時機(jī)?

我們前面已經(jīng)知道,當(dāng)插入記錄的輔助索引頁不在緩沖池中的時候,需要將輔助索引記錄插入到這棵B+樹中,后續(xù)會從insert buffer中往真正的輔助索引中進(jìn)行合并,那么什么時候進(jìn)行合并呢?

1、輔助索引頁被讀取到緩沖池的時候

2、insert buffer Bitmap追蹤到該輔助索引頁已經(jīng)沒有足夠的可用空間時,一般的閾值是輔助索引頁空間的1/32

3、master thread每秒執(zhí)行一次merge insert buffer的操作

以上就是MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)的詳細(xì)內(nèi)容,更多關(guān)于Innodb特性之插入緩沖的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: MySQL 數(shù)據(jù)庫
相關(guān)文章:
主站蜘蛛池模板: 龙海市| 新绛县| 东宁县| 博乐市| 吴江市| 柞水县| 江源县| 开平市| 都江堰市| 隆化县| 高淳县| 四平市| 吉安县| 鲜城| 西盟| 正阳县| 铁岭市| 张家川| 乌拉特后旗| 建始县| 北辰区| 南昌县| 九江市| 镇安县| 财经| 余庆县| 青川县| 醴陵市| 绍兴县| 浦江县| 溧阳市| 沾益县| 分宜县| 花垣县| 天镇县| 日土县| 河南省| 梅州市| 金昌市| 习水县| 新晃|