自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

不知道 Insert Buffer 的請(qǐng)舉手

運(yùn)維 數(shù)據(jù)庫(kù)運(yùn)維
在講插入緩沖這個(gè)振奮人心的 InnoDB 新特性之前,我們有必要先來(lái)回顧下 Buffer Pool(緩存池)的概念。

[[434991]]

Buffer Pool 緩沖池回顧

在講插入緩沖這個(gè)振奮人心的 InnoDB 新特性之前,我們有必要先來(lái)回顧下 Buffer Pool(緩存池)的概念。

前文說(shuō)過(guò),InnoDB 存儲(chǔ)引擎是基于磁盤存儲(chǔ)的,并將其中的記錄按照頁(yè)的方式進(jìn)行管理。因此可將其視為基于磁盤的數(shù)據(jù)庫(kù)系統(tǒng)(Disk-base Database)。為了緩解 CPU 與磁盤速度之間的矛盾,基于磁盤的數(shù)據(jù)庫(kù)系統(tǒng)通常使用緩沖池技術(shù)來(lái)提高數(shù)據(jù)庫(kù)的整體性能。

緩沖池其實(shí)就是一塊內(nèi)存區(qū)域,沒(méi)什么特別的。

  • 對(duì)于數(shù)據(jù)庫(kù)中頁(yè)的讀取操作,首先會(huì)將從磁盤讀到的頁(yè)存放在緩沖池中,這個(gè)過(guò)程也稱為將頁(yè) FIX 在緩沖池中。這樣,下一次再讀相同的頁(yè)時(shí),如果該頁(yè)是否在緩沖池中,則直接讀取該頁(yè)就行了,不用去磁盤上讀取。
  • 對(duì)于數(shù)據(jù)庫(kù)中頁(yè)的修改操作,則首先修改在緩沖池中的頁(yè),然后再以一定的頻率刷新到磁盤上。

簡(jiǎn)單來(lái)說(shuō),緩沖池就是通過(guò)內(nèi)存的速度來(lái)彌補(bǔ)磁盤速度較慢對(duì)數(shù)據(jù)庫(kù)性能的影響。

當(dāng)然了,緩沖池畢竟不是無(wú)限大的,不能把所有的數(shù)據(jù)都存在緩沖池上面,InnoDB 通過(guò)一種稱為 Checkpoint 的機(jī)制來(lái)決定哪些數(shù)據(jù)該從緩沖池移出去(移到磁盤上),這個(gè)在前面文章中我們也解釋過(guò)啦,遺忘的小伙伴可以翻看下前文。

Insert Buffer 插入緩沖

Insert Buffer 這個(gè)名字可能會(huì)讓小伙伴們認(rèn)為它是 Buffer Pool 中的一個(gè)組成部分。其實(shí)不然,Insert Buffer 是物理頁(yè)的一個(gè)組成部分,是一顆 B+ 樹(shù),頁(yè)是存在磁盤中的,而 Buffer Pool 它是一塊內(nèi)存區(qū)域。

不過(guò),需要注意的是,Buffer Pool 中會(huì)包含 Insert Buffer 的某些信息,來(lái)看下 InnoDB 存儲(chǔ)引擎的內(nèi)存結(jié)構(gòu):

可以看到,Innodb Buffer Pool 包含的數(shù)據(jù)頁(yè)類型有:索引頁(yè),數(shù)據(jù)頁(yè),undo 頁(yè),Insert Buffer,自適應(yīng)哈希索引,鎖信息,數(shù)據(jù)字典信息等。

以問(wèn)題為導(dǎo)向,對(duì)于 Insert Buffer,我們需要弄清楚的其實(shí)就 2 個(gè)問(wèn)題:

  • Insert Buffer 能解決什么問(wèn)題?
  • 什么情況下能夠使用 Insert Buffer?

通常,我們?cè)诮ū淼臅r(shí)候,都會(huì)給主鍵定一個(gè)自增長(zhǎng)(AUTO_INCREMENT)的特性,也即主鍵按照遞增的順序進(jìn)行插入。上篇文章講過(guò),聚集索引一般建立在主鍵上面,也就是說(shuō),插入聚集索引一般是順序的,不需要經(jīng)過(guò)磁盤的隨機(jī)讀取。

舉個(gè)例子:

  1. CREATE TABLE user
  2.  id INT(11) AUTO_INCREMENT,   
  3.     username VARCHAR(30),   
  4.     PRIMARY KEY(id) 
  5. ); 

id 是自增長(zhǎng)的主鍵,我們?cè)诓迦胍粋€(gè)新的行記錄的時(shí)候,無(wú)須對(duì) id 賦值或者說(shuō)賦 NULL 值,存儲(chǔ)引擎會(huì)幫助我們將這個(gè)值自動(dòng)增長(zhǎng)。

同時(shí)頁(yè)中的行記錄是按照主鍵 id 的值進(jìn)行順序存放的,所以,在我們插入新的行記錄的時(shí)候,一般來(lái)說(shuō)磁盤是不需要去隨機(jī)讀取另一個(gè)頁(yè)中的記錄的,因此速度非??臁?/p>

當(dāng)然了,并不是說(shuō)所有的主鍵插入都是順序的。有些業(yè)務(wù)場(chǎng)景下可能需要用 UUID 這種作為主鍵,即使它被定義了自增長(zhǎng)類型,如果每次插入的都是通過(guò) UUID 生成的指定值,而不是 NULL,那么顯然它的插入就是隨機(jī)的了。

這樣分析下來(lái)似乎我們的插入性能會(huì)比較好,但是,不可能一張數(shù)據(jù)庫(kù)表上只有一個(gè)聚集索引吧,還有其他的輔助索引呢。事實(shí)上,輔助索引也確實(shí)是影響插入性能的關(guān)鍵。

舉個(gè)例子,我們定義一個(gè)非聚集的且不是唯一的索引 username:

  1. CREATE TABLE user
  2.  id INT(11) AUTO_INCREMENT,   
  3.     username VARCHAR(30),   
  4.     PRIMARY KEY(id), 
  5.     key(username) 
  6. ); 

在進(jìn)行插入操作時(shí),數(shù)據(jù)頁(yè)的存放確實(shí)還是按自增長(zhǎng)的主鍵 id 來(lái)進(jìn)行順序存放的,這沒(méi)錯(cuò)。

但是,索引的本質(zhì)是什么?是 B+ 樹(shù),是一個(gè)存在磁盤上的物理文件。那我們?cè)跇?gòu)建輔助索引 username 的這棵 B+ 樹(shù)的時(shí)候,非聚集索引葉子節(jié)點(diǎn)的插入不再是順序的了,也就是說(shuō)要去離散地訪問(wèn)磁盤頁(yè)了。

正是由于隨機(jī)讀取的存在導(dǎo)致了插入操作性能下降。

和 “不是所有的主鍵插入都是順序的” 類似,在某些情況下,輔助索引的插入可能也是順序的,或者說(shuō)是比較有順序的。

比如用戶表中有一個(gè)時(shí)間字段,用來(lái)表示用戶買下某個(gè)物品的時(shí)間。在通常情況下,用戶購(gòu)買時(shí)間是一個(gè)輔助索引,用來(lái)根據(jù)時(shí)間條件進(jìn)行查詢。但是在插入時(shí)卻是根據(jù)時(shí)間的遞增而插入的,因此插入也是比較有順序的。

至此,講了半天好像還沒(méi)有看見(jiàn) Insert Buffer 的影子?

別急,這就來(lái)。

InnoDB 存儲(chǔ)引擎開(kāi)創(chuàng)性地設(shè)計(jì)了 Insert Buffer。對(duì)于輔助索引的插入或更新操作,并不是每一次直接插入到索引頁(yè)(磁盤頁(yè))中,而是先判斷插入的輔助索引頁(yè)是否在 Buffer Pool 中:

  • 若在,則直接插入;
  • 若不在,則先將其放入到一個(gè) Insert Buffer 對(duì)象中,就好像騙了數(shù)據(jù)庫(kù)一波:告訴數(shù)據(jù)庫(kù)這個(gè)輔助索引的葉子節(jié)點(diǎn)了已經(jīng)插入成功了(磁盤上),但是實(shí)際上并沒(méi)有,只是存放在內(nèi)存里的 Insert Buffer 中。

當(dāng)然,不能將這個(gè)葉子節(jié)點(diǎn)一直存在 Insert Buffer 中,對(duì)吧,這個(gè)輔助索引的 B+ 樹(shù)終歸還是得建立起來(lái)的。具體來(lái)說(shuō),InnoDB 會(huì)以一定的頻率和情況進(jìn)行 Insert Buffer 和輔助索引頁(yè)子節(jié)點(diǎn)的 Merge(合并)操作,這時(shí),就相當(dāng)于將多個(gè)葉子節(jié)點(diǎn)插入操作合并到一個(gè)操作中(因?yàn)樵谝粋€(gè)索引頁(yè)中),這就大大提高了對(duì)于輔助索引插入性能

簡(jiǎn)單概括下:Insert Buffer 就是一棵 B+ 樹(shù),若需要實(shí)現(xiàn)插入記錄的輔助索引頁(yè)不在 Buffer Pool 中,那么需要將輔助索引記錄首先插入到這棵 B+ 樹(shù)中,然后在適當(dāng)?shù)那闆r下將其合并(Merge)到真正的輔助索引中。

舉個(gè)現(xiàn)實(shí)生活中的例子來(lái)說(shuō):

我們?nèi)D書(shū)館還書(shū),對(duì)于圖書(shū)館管理員來(lái)說(shuō),他需要做的就是 insert 操作,管理員在 1 小時(shí)內(nèi)接受了 100 本書(shū),這時(shí)候他有 2 種做法把還回來(lái)的書(shū)歸位到書(shū)架上:

  • 每還回來(lái)一本書(shū),就把這本書(shū)送回架上
  • 暫時(shí)不做歸位操作,等到空閑下來(lái)了,再把這些書(shū)一次性送回書(shū)架上

用方法 1,管理員需要進(jìn)出圖書(shū)管 100 次,不停的登高爬低完成圖書(shū)歸位操作,累死累活,效率很差。

用方法 2,管理員只需要對(duì)要?dú)w位的書(shū)進(jìn)行一個(gè)分類,進(jìn)出圖書(shū)管 1 次,對(duì)同一個(gè)位置的書(shū),不管多少,都只要爬一次樓梯,大大減輕了管理員的工作量。

那么,什么條件下可以使用 Insert Buffer 以此來(lái)提高插入操作的性能呢?

  • 索引是輔助索引
  • 索引不是唯一索引

為什么 Insert Buffer 不適用于唯一的輔助索引呢?

一個(gè)很簡(jiǎn)單的套娃問(wèn)題(滑稽):

如果輔助索引是唯一的,那么當(dāng)把要插入的對(duì)象存到 Insert Buffer 時(shí),數(shù)據(jù)庫(kù)就需要去磁盤上查找索引頁(yè)來(lái)判斷插入記錄的唯一性,顯然,如果去查找就會(huì)有離散讀取的情況發(fā)生,從而導(dǎo)致 Insert Buffer 失去了意義。

還以圖書(shū)管那個(gè)例子來(lái)說(shuō):

如果圖書(shū)館中所有的書(shū)只允許存在一本,那我們還一本書(shū)到圖書(shū)館的時(shí)候,管理員就必須爬到圖書(shū)管的指定位置去確認(rèn)判斷一下這本書(shū)是不是唯一的,這個(gè)過(guò)程就相當(dāng)于產(chǎn)生了一次 IO 操作了。

另外,Insert Buffer 有利有弊,考慮一種極端情況:

如果數(shù)據(jù)庫(kù)中涌入了大量的插入操作,并且這些都涉及了不唯一的非聚集索引,也就是使用了 Insert Buffer。若此時(shí)數(shù)據(jù)庫(kù)崩潰了,這時(shí)勢(shì)必有大量的 Insert Buffer 沒(méi)有被合并到實(shí)際的輔助索引中去,那么這時(shí)候的恢復(fù)就可能需要很長(zhǎng)的時(shí)間。

Change Buffer

InnoDB 從 1.0.x 版本開(kāi)始引入了 Change Buffer,現(xiàn)在有些博客上說(shuō)的也是 Change Buffer,容易讓小白懵逼,其實(shí)就是 Insert Buffer 的升級(jí)版。

從這個(gè)版本開(kāi)始,InnoDB 存儲(chǔ)引擎可以對(duì) DML 操作 — INSERT、DELETE、UPDATE 都進(jìn)行緩沖,他們分別對(duì)應(yīng)的是:Insert Buffer、Delete Buffer、Purge buffer

同樣的,和之前 Insert Buffer 一樣,Change Buffer 適用的對(duì)象依然是非唯一的輔助索引。

對(duì)一條記錄進(jìn)行 UPDATE 操作可能分為兩個(gè)過(guò)程:

 

  • 將記錄標(biāo)記為已刪除:對(duì)應(yīng) Delete Buffer
  • 真正將記錄刪除:對(duì)應(yīng) Purge Buffer

 

責(zé)任編輯:武曉燕 來(lái)源: 飛天小牛肉
相關(guān)推薦

2021-03-14 22:32:45

SQL數(shù)據(jù)庫(kù)XML

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket瀏覽器

2011-09-15 17:10:41

2022-10-13 11:48:37

Web共享機(jī)制操作系統(tǒng)

2009-12-10 09:37:43

2021-02-01 23:23:39

FiddlerCharlesWeb

2018-06-20 00:30:06

2010-08-23 09:56:09

Java性能監(jiān)控

2021-07-14 11:25:12

CSSPosition定位

2020-09-15 08:35:57

TypeScript JavaScript類型

2022-11-04 08:19:18

gRPC框架項(xiàng)目

2020-12-21 09:00:04

MySQL緩存SQL

2021-12-29 11:38:59

JS前端沙箱

2021-12-22 09:08:39

JSON.stringJavaScript字符串

2012-11-23 10:57:44

Shell

2015-06-19 13:54:49

2020-08-11 11:20:49

Linux命令使用技巧

2021-10-17 13:10:56

函數(shù)TypeScript泛型

2018-07-11 15:54:23

趨勢(shì)互聯(lián)網(wǎng)投資
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)