The Log-Structured Merge-Tree(譯):中

http://duanple.blog.163.com/blog/static/7097176720123202125771/

3.3 Multi-Component LSM-Trees

對於給定的LSM-tree,參數M代表了rolling merge過程中插入到每個C1樹的葉子節點中的C0樹的平均記錄數。在mergeC1樹的節點中之前,這些新記錄會首先在C0中積累一段時間,因此通常我們認爲M是大於1的。但是,通過公式(3.2){! M=(Sp/Se)·(S0/(S0+S1))}能夠看出,如果與C0樹相比C1樹足夠大,或者是單條記錄非常大以至於單個page中只能放下很少的記錄,那麼M的值就可能會小於1。這樣的一個M值意味着,爲了能將C0中的一條記錄移出內存將不得不讀入多個C1page。根據公式(3.4){! COST(LSM-ins)/ COST(B-ins)=K1·(COSTπ/COSTp)·(1/M)},在M< K1·(COSTπ/COSTp)的情況下,將會抵消掉multi-page的批處理效果,此時對於插入操作來說使用B-樹要比使用LSM-tree更划算。

 

爲了避免得到一個太小的M值,對於兩組件LSM-tree來說,只能通過增加C0C1的相對大小來解決。考慮一個葉子節點總大小爲S(S=S0+S1,一個近似穩定的值)的兩組件LSM-tree,同時假設新節點以一個不變的速率R(bytes/秒爲單位)插入到C0中。爲簡化起見,我們假設在被移入到C1中之前,沒有記錄會被刪除,因此這些記錄也必須以與它們被插入到C0中的相同的速率被移入到C1,以保證C0的值總是維持在閾值大小附近。(由於總大小S基本上是不變的,這也暗示着與插入到C0的速率相比,也需要一個與之平衡的從C1中進行刪除的速率,比如可能使用了斷言式刪除)。當我們改變C0的大小時,也會影響到merge遊標的循環週期。由於到C1的移出速率(每秒的字節數)需要保持不變,這樣就要求遊標每秒所掃描的數據保持不變,在C0大小減少時,很明顯遊標從最小值到最大值的掃描頻率必須要加快;這樣就導致C1中用於rolling merge過程的multi-page block IO也必須要加快。極端情況下,比如C0大小隻能存下一條記錄,這樣對於每個新插入的記錄,都需要完整地將C1掃描一遍,這將產生大量的IO需求。此時,這種將C0C1進行merge的方式,與B-樹中爲每個新插入記錄只需訪問相關節點的方式相比,將會帶來更大的性能瓶頸。與之相比,C0越大將越能增大merge遊標的掃描週期,從而降低插入所需的IO開銷。但是,這也會增加所需的內存開銷。

 

通常情況下,可以通過最小化LSM-tree的總開銷(用於C0的內存開銷加上用於C1的磁盤空間/IO能力開銷)來確定C0的大小。爲了達到這種最小化的開銷,我們通常從一個比較大的C0組件開始,同時讓C1組件大小接近於所需空間的大小。在C0組件足夠大的情況下,對於C1IO壓力就會很小。現在,我們可以開始試着通過減少C0的大小,來在昂貴的內存和廉價磁盤之間進行權衡,直到減低到當前C1所能提供的IO能力完全被利用爲止。此時,如果再降低C0的內存開銷,將會導致磁盤存儲開銷的增加,因爲需要擴充C1組件以應對磁盤負載的增加,最終將會達到一個最小開銷點。現在,對於兩組件LSM-tree來說,這個典型的C0組件大小從內存使用的角度上看開銷仍是比較高的。一個改進的方案是,採用一個三組件或者多組件LSM-tree。簡單來說,如果C0太大以至於內存開銷成爲主要因素,那麼我們可以考慮在兩組件LSM-treeC0C1之間加入一箇中間大小的基於磁盤的組件,這就允許我們在降低了C0大小的同時還能夠限制住磁盤磁臂的開銷。

 

通常,一個具有K+1個組件的LSM-tree具有組件C0,C1,C2…,Ck-1Ck,組件大小依次遞增;C0組件是基於內存的,其他都是基於磁盤的(對於那些經常訪問的頁面來說會被緩存在內存中)。在所有的組件對(Ci-1,Ci)之間都存在一個異步的rolling merge過程,它負責在Ci-1超過閾值大小時,將記錄從較小的組件中移入到較大的組件中。當一個生命期很長的記錄被插入到LSM-tree之後,它首先會進入C0樹,然後通過這一系列的K個異步rolling merge過程,最終將被移出到Ck

The Log-Structured Merge-Tree(譯):中 - 星星 - 銀河裏的星星
 

這裏我們主要關注插入性能,因爲我們假設LSM-tree通常使用在插入爲主的場景中。對於三組件或者多組件LSM-tree來說,查找操作性能上會有降低,通常一個磁盤組件將會帶來一次額外的頁面IO

3.4 LSM-treesComponent Sizes

在本節中,我們將會推導出具有多個組件的LSM-tree插入操作的IO開銷,同時會在數學上論證如何來爲各個組件選擇最優的閾值大小。同時會對例3.3進行一些擴展,用來說明B-樹的系統開銷,採用兩組件LSM-tree所帶來的改進後的系統開銷,以及三組件LSM-tree帶來的更大的節省。

 

我們將LSM-tree組件的大小,S(Ci),定義爲該組件葉子級別的記錄的字節數;同時用Si來作爲組件Ci的大小的縮寫,S(Ci)=Si,同時S代表所有組件的葉子級別的記錄的總大小,S=Sum(Si)。我們假設對於C0來說具有相對平穩的插入速率R,單位是bytes/秒,爲了簡化起見,假設所有新插入的記錄都會存活下來並會通過一系列的rolling merge步驟被移出到Ck。同時假設組件C0,C1,C2…,Ck-1,都具有一個與當前分析所確定的最大閾值近似的大小。同時假設組件Ck具有一個相對穩定的大小,因爲在一定的時間段內,刪除會將插入抵消掉。

 

給定一個具有固定總大小爲SC0組件大小爲S0K組件LSM-tree,該樹就可以通過變量ri(i=1,…k,代表了相鄰組件的大小之比,ri=Si/Si-1)來完整地描述了。如下所述,執行一個組件對(Ci-1,Ci)之間的正在進行中的merge操作的頁面IO頻率可以表示爲R(C0中的插入的頻率)ri的函數。同時我們假設不同組件的blocks將會混合的方式來使用不同的磁盤以達到磁盤磁臂利用率的平衡,這樣最小化H就等價於最小化總的磁盤磁臂開銷(至少在磁盤磁臂開銷而非磁盤容量在成本中起決定性作用的情況下是這樣的)。這樣對於給定的R,找到可以使總的IO請求率H最小化的ri值的問題,就變成了一個標準了微積分最小化問題。在總大小S固定不變的假設下,由於ri值之間的複雜的遞歸關係將會使它變成一個很難解的問題。但是如果我們假設Sk是固定不變的(S0也是固定不變的),如Theorem3.1,當所有的ri值等於某個常數r時,就可以取得最小值。同時我們也通過Theorem3.2給出了在總大小S爲常量時的,關於ri值的一個更爲精確的解,同時也可以看到對於ri所取常量r值,基本上已經給出了非常類似的結果。假設所有的ri都取r值,那麼就有Si=(r^i)·S0。同時總大小可以表示爲各組件的大小之和,S=S0+r·S0+(r^2)·S0+…+(r^k)·S0,因此我們就可以用SS0來表示r

 

根據Theorem3.1,對於給定的SkS0和插入頻率R,爲了最小化多組件LSM-tree的總的IO頻率,我們需要讓最大組件Sk和最小組件S0之間的組件大小具有幾何級數的增長關係。另外我們將會發現,對於兩組件LSM-tree的情況,如果我們令RSk保存不變,而允許S0可變,那麼H就可以表示爲S0的函數,同時隨着S0的減小H會增大。現在我們可以通過改變S0的大小,來最小化LSM-tree的總開銷(內存+磁盤磁臂開銷)。例3.3演示瞭如何根據給定數目的組件來獲得最優的總開銷。現在總開銷中剩下的唯一的自變量就是組件數目,K+1了。在本節的最後我們會討論如何調節這個值。

 

Theorem3.1 給定一個最大組件大小爲Sk,插入頻率爲R和內存組件大小爲S0的具有K+1個組件的LSM-tree,在比率ri=Si/Si-1等於同一個值r時,執行所有merge的總的頁面IO頻率H將可以取得最小值。這樣總大小S就可以表示爲各組件大小之和:

 

(3.5) S=S0+r·S0+(r^2)·S0+…+(r^k)·S0

 

這樣我們就可以將rSS0表示出來。類似的,總的頁面IO頻率H可以表示爲:

 

(3.6)H=(2R/Sp)·(K·(1+r)-1/2)Sp代表每個頁面的字節數

 

證明:因爲我們已經假設在記錄到達組件Ck之前都不會刪除,很明顯從組件Ci-1Cirolling merge過程的記錄移出率應與插入到C0的頻率R(bytes/秒爲單位)是一致的,對於所有的i0<i<=K。考慮Ci-1爲磁盤組件的情況,從Ci-1Cirolling merge過程將會包含從Ci-1中以每秒R/Sppagemulti-page block讀取,此處Sp代表每個頁面的字節數(通過假設所有碰到的記錄都會從Ci-1中刪除,我們根據R計算出了每秒從Ci-1中移出的記錄數目;在普通情況下,其他的假設也是可能的)。該merge過程還會包含從Ci中以每秒ri·(R/Sp)pagemulti-page block讀取(這是因爲rolling merge遊標在掃描到的Ci中的page個數是Ci-1中的ri=Si/Si-1)。最後該merge過程還會引入每秒(ri+1)·(R/Sp)pagemulti-page磁盤寫入來將屬於Cimerge出的新數據寫出。需要注意的是,在這裏我們考慮到了因爲merge引起的Ci組件的增大{!數據從ri·(R/Sp)變成了(ri+1)·(R/Sp)page}。將所有磁盤組件的Ci對應值相加,就可以得到總的multi-page IO大小H(以每秒的pages數爲單位)

 

(3.7)H=(R/Sp)·((2·r1+2) + (2·r2+2) + … +(2·rk-1+2) + (2·rk+1))

 

每一項的(2·ri+k)代表了在組件Ci上的所有IOri·(R/Sp)用於爲從Ci-1Cimerge讀入屬於Ci中的數據,(ri+1)·(R/Sp)用於爲該merge將數據寫出到Ci,而R/S0則用於爲從CiCi+1merge而讀入屬於Ci的數據。很明顯對於C0來說,沒有該項開銷,而對於Ck來說則沒有最後的那一項R/S0。因此公式(3.7)可以重新改寫爲:

 

(3.8)H=(2R/Sp)( Σ(ri)+k-1/2)i[1…k]

 

我們希望可以在如下條件下:Π(ri)=(Sk/S0)=C, i[1…k]{!根據之前的假設,我們知道S0Sk均爲常數,而Sk=(r1·r2…rk)·S0,故(r1·r2…rk)也是一個常數},可以最小化該函數值。爲了解決這個問題,需要最小化Σ(ri),我們將rk使用C·Π(1/ri)i[1…k-1]來替換掉{!根據Π(ri)=C,即可得rk= C·Π(1/ri)}。然後對每個自變量rjj=1,…k-1計算其偏導數,同時令它們等於0,我們將會得到如下形式的一系列等式:0=1-(1/rj) C·Π(1/ri)i=1,…k-1,很明顯,當所有的rj(包括rk)等於C·Π(1/ri) 時,i=1,…k-1,或C^(1/k)時有解。

{!上面的問題本質上是如下的一個問題,K個正數的乘積爲一定值,求這K個數的和的最小值,具體推導過程如下:

Σ(r1…rk)

Σ(r1…rk-1)+ C·1/Π(r1…rk-1) //使用C·Π(1/ri)替換rk

Σ(r1…rk-1)+ 1/rj·C·1/Π(r1…rj-1,rj+1…rk-1) //rj提到前面

=1-(1/(rj·rj)) C·1/Π(r1…rj-1,rj+1…rk-1) //rj進行求導

=1-(1/rj) C·Π(1/ri) //將其中一個rj放到後面

}

 

Theorem3.2 現在我們修改Theorem3.1中關於Sk大小爲常數的假設,而是設總大小S爲常數。這個最小化問題就變得更困難了,但是依然是可以通過拉格朗日乘數來解的。結果可以表示如下:

rk-1=rk+1

rk-2=rk-1+1/rk-1

rk-3=rk-2+1/(rk-1·rk-2)

我們忽略其證明過程。

 

正如我們通常所見到的,ri的值通常都是比較大的,比如是20或者更大,因此這個最大組件的大小,Sk通常佔據了總大小S的絕大部分。因此對於Theorem3.2來說,每個ri只是與它相鄰的那個ri+1有個細微的差異。因此,在下面的例子中,我們還是基於Theorem3.1的結果來進行說明。

 

最小化總開銷

 

通過Theorem3.1,可以看出如果讓RSk保存不變,而允許S0變化,那麼就可以將總的IO頻率H表示爲S0的函數。

根據公式(3.5) S=S0+r·S0+(r^2)·S0+…+(r^k)·S0r會伴隨着S0的減小而增大,

又根據(3.6) H=(2R/Sp)·(K·(1+r)-1/2)Hr成正比

很明顯H會隨着S0的減小而增大。現在我們可以看下如何通過在昂貴內存與廉價磁盤間進行權衡,來讓兩組件LSM-tree的總開銷最小化。我們需要計算出用於存儲LSM-tree所需的磁盤空間,以及可以讓磁盤磁臂完全被利用所需要的總IO頻率H,同時我們將此作爲我們用於決定可以最小化開銷的S0大小的計算的起點{!即先確定出一個H的初始值,而因爲HS0相互之間具有固定的關係,然後就可以根據這個H再計算出S0的一個初始值}。從這個點開始,如果我們繼續減少C0大小,那麼磁盤介質的開銷就需要增加了,因爲此時磁盤磁臂開銷已經成爲了限制因素。下面的例3.3就針對兩組件和三組件LSM-tree,解釋了這樣的一個過程。在講這個例子之前,我們首先針對兩組件情況進行一些分析。

 

總開銷是內存開銷,COSTm·S0,和磁盤開銷,磁盤開銷是由磁盤存儲和IO開銷中的最大值決定的,在這裏IO開銷基於multi-page block訪問頻率H(pages/秒爲單位)

 

COSTtot= COSTm·S0+max[COSTd·S1COSTπ·H]

 

考慮兩組件的情況,對於公式(3.6)k=1r=S1/S0。令:

s= (COSTm·S0)/(COSTd·S1)=內存開銷與S1數據的存儲開銷之比

t=2·((R/Sp)/S1)·(COSTπ/COSTd)·(COSTm/COSTd)

C=COSTtot/(COSTd·S1)=總開銷與S1數據的存儲開銷之比

 

那麼,利用式(3.6)進行替換和簡化後,同時假設S0/S1值很小,可以得出如下的近似等式:

Cs+max(1,t/s)

{!推導過程如下:

C=COSTtot/(COSTd·S1)

 = (COSTm·S0+max[COSTd·S1COSTπ·H])/( COSTd·S1)

 =(COSTm·S0) /( COSTd·S1)+max[1, COSTπ·H/( COSTd·S1)]

H=2(R/Sp)(r+1/2)代入

 =s+max[1,2((R/Sp)/S1)( COSTπ/COSTd)(r+1/2)]

 =s+max[1,2((R/Sp)/S1)( COSTπ/COSTd)(COSTm/COSTd)(COSTd/COSTm)(r+1/2)]

 = s+max[1,t(COSTd/COSTm)(r+1/2)

r=S1/S0

 s+max[1,t(COSTd/COSTm)(S1/S0)

s+max[1,t(COSTd·S1)/(COSTm·S0)]

s+max[1,t/s]

同時這也意味着COSTπ·H/( COSTd·S1)t/s

}

這樣相對開銷C就是變量ts的函數;變量t實際上是應用程序所需的multi-page block IO頻度的某種形式化表示{!可以看到對於t來說,COSTπ/COSTd體現的是磁盤IO與空間開銷之比,COSTm/COSTd 體現的內存開銷與磁盤開銷之比,這兩個值是兩個常量,而((R/Sp)/S1)則體現的是數據的訪問密度,如果R越大,則t越大}s則代表了爲實現LSM-tree我們所需要提供的內存大小。爲確定S0的大小,最簡單地規則就是,沿着s=t這個分界線,此時C=s+1,同時磁盤存儲和IO能力都已被完全利用{!s=t,根據COSTπ·H/( COSTd·S1)t/s說明此時COSTd·S1= COSTπ·H也就是說磁盤存儲空間所具有的IO能力已完全被利用 }。對於t<=1時,在s=t時可以取得最小值,但是對於t>1C的最小值是沿着曲線s=t^(1/2)的,此時C=2·t^(1/2),將該結論代入到我們前面的等式中,可得到,對於t>=1

 

(3.8)COSTmin=2[(COSTm·S1)(2·COST·R/Sp)]^(1/2)

{!COSTminmin(COSTtot)}

 

因此在t>=1的情況下,LSM-tree的總開銷看起來是(足以將所有LSM數據保存下來的所需內存的開銷,這是一個很高的值,即COSTm·S1)(用於支持將插入數據寫入到磁盤所需的multi-page block IO的磁盤開銷,這是一個很低的值,即2·COST·R/Sp)的幾何平均數的2倍。總開銷中的一半將會被用於S0的內存開銷,剩下的一半用於對於S1IO訪問開銷。磁盤存儲空間的開銷並沒有體現出來,因爲t>=1保證了數據是足夠熱的足以讓IO開銷佔據磁盤開銷的主導。

 

t<=1的情況下,數據較冷的情況下,在s=t時可取得最小化開銷,此時C=t+1<2。這意味着這種情況下的總開銷總是不會超過用於將S1存儲在磁盤上的開銷的兩倍。在這種情況下,我們會根據存儲開銷來決定磁盤大小,然後通過利用起它所有的IO能力來最小化內存使用。

{!我們可以將上面的分析過程轉換爲一個更純粹的數學問題。t基本上可以看做一個常量,tR是直接相關的,它標識了數據訪問的熱度,因此對於C的最小值計算實際上是在求如下曲線的最小值

Cs+max(1,t/s)

Cmax(s+1,s+t/s)

由於t可看做一常量,這樣我們就可以將上面等式用平面座標系中的曲線進行表示。y=x+1y=x+c/x,根據解析幾何知識可知,y=x+1是直線,而y=x+c/x則是如下形狀曲線。

The Log-Structured Merge-Tree(譯):中 - 星星 - 銀河裏的星星
 

x->正無窮時,c/x->0,所以曲線無限接近y=x,而在x->0時,c/x->正無窮。最小值點可以通過對其求導數求得,在x=c^(1/2)時取得,此時y=2 c^(1/2)。下面需要求的則是y=max(x+1,x+c/x),因此需要將該曲線y= x+c/xy=x+1進行比較。

x+1>x+c/x,可得x>c

x+1<x+c/x,可得x<c

也就是說以x=c作爲分界點,y=max(x+1,x+c/x)取值如下:

x>c時,y =x+1,而

x<c時,y=x+c/x

y=max(x+1,x+c/x)就變成了一個分段函數,在x=c處分成了兩個函數。那麼下面的事情就是要看如何計算該分段函數的最小值了。

 

對於該分段函數來說,其在哪點取得最小值實際上就是與c的取值相關了,同時最小值點只有兩種可能:一是在y=x+1y=x+c/x的交點處,一是在y=x+c/x的最小值點處。如果c=1,那麼y=x+1y=x+c/x的交點就剛好是y=x+c/x的極值點,也就是說此時在x=c處即是最小值點,而在c<1時,二者交點在(c,c+1)處,但y=x+c/x的極值點在(c^(1/2),2 c^(1/2)),同時由於c<1c^(1/2)>c,而我們的分段函數,在x>c處,曲線是y=x+1,因此此時的最小值應是在(c,c+1)處。只有當c>1時,c^(1/2)<c,此時分段函數曲線纔是y=x+c/x,同時2c^(1/2)<c+1,因此此時的最小值點應是(c^(1/2),2 c^(1/2))

}

 

3.3 我們來考慮下例3.1中涉及的Account-ID||Timestamp索引。下面的分析只是計算出了在插入速率R16,000bytes/(100016字節的索引記錄,忽略其他開銷,這樣所產生的20天的索引數據將具有576,000,000個記錄,總大小約9.2GBytes)時,對應插入操作的開銷。

 

如我們在例3.1中所見,如果使用B-樹來進行索引支持,那麼磁盤IO會成爲限制因素葉級數據是warm的。即使假設所有的非葉子節點都是駐留在內存中的,仍然需要我們提供足夠的磁盤空間以支持H=2,000個隨機IO/秒,來滿足葉級節點隨機性的頁面更新的需求。如果採用3.1節裏的COSTp=$25,可以算出IO開銷是H·COSTp=$50,000。下面我們再計算下用於將上層節點緩存在內存的開銷。假設葉節點是70%滿的,那麼每個葉節點就有0.7·(4K/16)=180個記錄,因此在葉級節點之上大概會有576,000,000/180=3,200,000個節點指向下面的葉子節點。如果我們採用一些前綴壓縮,那麼我們就可以在該級別上的每個節點中放下200條記錄,這意味着將會有16,000{!3,200,000/200}4Kbytes大小的頁面,總大小爲64Mbytes,按照COSTm=$100/Mbytes算的話,就是$6400。我們忽略在該級別之上的那些節點的相對較小的緩存開銷,那麼B-樹的總開銷就是由$50,000的磁盤開銷和$6400的內存開銷組成,合起來就是$56,400

 

對於一個具有兩個組件C0C1LSM-tree來說,我們需要一個大小S1=9.2GB的磁盤來保存記錄,開銷就是COSTd·S1=$9,200。我們會將數據在磁盤上緊密放置,同時計算出在這個容量大小下的磁盤在使用multi-page block IO的情況下所能支持的總IO速率H,實際上H=9200/COSTπ=3700pages/秒。現在根據這個H值,以及R=16,000bytes/秒,Sp=4K,再結合公式(3.6),就可以解出r

{!(3.6)H=(2R/Sp)·(K·(1+r)-1/2),對於兩組件LSM-tree來說K=1,代入已知參數可得3700=(2·16,000/4000)·(r+1/2),解之得:r=3700/8-1/2=460}

根據r=S1/S0=460,以及S1=9.2GB,可得S020Mbytes,就需要$2000。這就是簡單地令s=t的情況下的解,總的開銷就是$11,200,同時磁盤的容量和IO已經被完全利用。因爲此時t=0.22,故還屬於<1的情況因此這個解也就是最優解。我們可以再增加$200來爲正在被mergeblock購置2Mbytes的內存,那麼總的開銷就達到了$11,400。與B-樹的$56,400相比已經是非常大的改進了。

 

更詳細地說,插入速率R=16,000bytes/秒,意味着每秒需要有4個頁面(每個頁面4KB)C0 mergeC1。因爲C1大小大概是C0460倍,那麼C0中的每條記錄merge時平均需要牽連到C1中的460條記錄。因此將C0中的一個頁面的merge需要讀寫C1中的460個頁面,每秒就是3680(C0每秒4個,4·460·2=3680)個頁面。這也是9.2個磁盤在使用multi-page block IO的情況下所能提供的IO能力,每個提供了400pages/{!根據前面所述,單磁盤隨機IO大概是40pages/秒,multi-page block IO大概是普通隨機IO10}

 

由於這個例子已經表明在具有兩個組件時,磁盤資源已經被完全利用,因此這裏也就沒有必要引入三組件LSM-tree。下面的例子展示了一個三組件LSM-tree可以爲純插入負載提供更少的開銷的情況。

 

3.4 考慮例3.3,令R增長10倍。現在B-樹解決方案爲支持H=20,000IO/秒的IO頻率要花費$500,000來購買500GB的磁盤;其中有491GB的空間將會是空閒的。但是B-樹本身的大小是相同的,因此我們仍然需要爲將目錄節點緩存下來而支付$6400,這樣總開銷就是$506,400。對於LSM-tree來說,如果R增長了10倍,意味着t也增長了同樣的倍數,即從0.22增長到了2.2。因此現在t就是大於1的了,那麼此時最優的兩組件解決方案已無法利用起所有的磁盤能力{?爲何?}。我們利用公式(3.8)來計算出兩組件LSM-tree的最小開銷爲$27,000,其中一半用於13.5GB的磁盤,一半用於135MB的內存。此時,仍有4.3GB的磁盤空間未被使用,加上用於緩存的2MB內存,總開銷是$27,200

 

更詳細地來說,插入頻率R=160,000bytes/秒,意味着每秒需要有40個頁面(每個頁面4KB)C0 mergeC1。因爲C1大小大概是C068倍,因此將C0中的一個頁面的merge需要讀寫C1中的68個頁面,每秒就是5440(C0每秒40個,40·68·2=5440)個頁面。這也是13.5個磁盤在使用multi-page block IO的情況下所能提供的IO能力。

 

對於使用一個三組件LSM-tree來處理這種R=160,000bytes/秒的情況,可以按照兩組件的那種方式先計算出最大的那個磁盤組件的一個開銷以及IO頻率的一個開銷平衡點。根據理論3.1,我們有Si/Si-1=ri=1,2,我們可以計算出r=23並且S0=17MB(內存開銷就是$1700)

{!與例3.3類似的計算方法,根據(3.6)H=(2R/Sp)·(K·(1+r)-1/2),對於三組件LSM-tree來說K=2,代入已知參數可得:

3700+3700/r=(2·160,000/4000)·(2·(1+r)-1/2)

解這個二元一次方程得:r=23S0=S2/(23·23)=17MB,爲存放下所有數據S2=9.2GB}

現在從這個點開始繼續增加內存的大小不會得到更好的性價比,因爲內存大小的降低,將會導致相應的磁盤開銷的平方級別的增長。因此我們可以得到一個針對三組件的類似的s=t解決方案。在加一個4MB內存用於爲兩個rolling merge過程緩存數據,需要$400,這樣對於三組件LSM-tree的總開銷就是$9200的磁盤開銷,加上$2100的內存開銷,總共就是$11,300,又比兩組件LSM-tree的開銷降低了很多。

 

更詳細地來說,內存組件C0大小爲17MB,稍小的那個磁盤組件大小C1是它的23倍,大概是400MBC2又比C123倍,是9.2GB。那麼每個頁面在從C0 mergeC1時,將會引入23個頁面讀和23個頁面寫操作,這樣每秒就需要讀寫1840(40*23*2)個頁面。類似的,每秒也需要有40個頁面從C1 mergeC2,每個頁面也會引入23個頁面讀和23個頁面寫操作,這樣每秒也會需要讀寫1840(40*23*2)個頁面{!?有些疑問,按照之前的說法,rolling merge過程,組件越大需要的IO量應該是越多,爲何此處變成一樣了呢?}。這樣總的IO頻率就是3680,剛好是9.2G的磁盤在使用multi-page block IO的情況下所能提供的IO能力。

 

與普通B-樹相比,對於查詢操作來說,兩組件或三組件LSM-tree需要更多的IO。對於它們來說,最大的那個組件就非常像一個獨立的B-樹結構,但是對於LSM-tree的情況,我們還沒有付出爲緩存那些索引中的葉級以上的節點而產生的$6400的內存開銷。因爲在樹中的那些很高層的節點相對很少,基本可以忽略,同時我們還可以假設它們已經被緩存了。但是,如果查詢頻率足夠高我們也很樂意花錢來將所有的目錄節點緩存起來。在三組件的情況下,我們還需要考慮C1組件。因爲它比最大的那個組件小23倍,因此我們也可以很容易地緩存它的所有非葉子節點,同時我們把這個開銷計入到我們的分析中。在某個C2中的記錄被查找時,如果訪問到C1中的一個未被緩存的節點將會引入一次額外的讀,同時也需要決定是否緩存C2的目錄節點。因此,對於三組件情況來說,查詢操作將可能會需要讀取一些額外的頁面而超過簡單B-樹結構所需的2IO。對於兩組件的情況,可能需要一次額外的讀。如果我們爲緩存LSM-tree組件的那些非葉子節點購置了足夠的內存,那麼對於兩組件的情況我們就能達到B-樹的訪問速度,對於三組件的情況可能只在某些時候需要一次額外的讀。加上緩存的開銷後,三組件LSM-tree的開銷就變成了$17,700,仍然遠小於B-樹。但是可能可以以更好的方式來用這些錢:一個充分的分析需要能夠最小化在所有工作負載(包括更新和查詢)上的總開銷。

 

我們已經根據定理3.1通過改變ri的大小來達到了使得merge操作的所需的IO的最小化。然後又通過選擇S0來使得總開銷最小化,以得到最好的磁盤磁臂和內存開銷。現在對於LSM-tree來說,唯一可變的就是組件個數,K+1了。實際證明,當我們增加組件個數的時候,S0將會不斷減少直到到達某個固定點,此時組件間的大小比率將會達到一個值e=2.71…….,或者直到到達cold-data區域。但是,通過例3.4可以看出,隨着組件數的增加,S0對總開銷的影響將會越來越小;在三組件LSM-tree的情況下,S0的大小已經降低到17MB。此外,隨着組件數目的增長還會伴隨着其他的開銷:需要有更多的CPU來執行更多的rolling merge過程,需要有更多的內存來緩存這些merge過程中的節點(甚至可能會查過C0的內存開銷)。此外查詢操作將需要在所有的組件樹中進行查找。如上這些原因就對組件的數目加上了很多限制,通常實際中最常見的的就是三組件的情況。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章