Hyperion圖片,Hyperion
在前面的內容中,筆者解釋過固定Span的Trie,在工程實踐中,經常使用的是1B的Span,對應的最大fanout是256。但是這種固定1B的Span,在離散數據集下,面臨著大多數中間節點的fanout都非常小,導致索引節點空間占用很高的問題。在Height Optimized Trie這篇論文中,作者通過使用不同的Span以及Structure Adaption算法來解決fanout小的問題。其實還有一種思路是使用更大的固定Span,例如使用2B,對應的最大fanout是65536,并且可以減少一層指針指向。通常情況下我們容易想到的是下面右圖這種組織方式,其中的每個節點是一個65536長度的數組,可以看到和左圖相比,樹的高度、節點的fanout以及指針數目要優于左圖,但是在空間占用上要高出左圖很多,因此我們需要一種更精細化的布局方式來降低空間占用。這就引出了本文的內容,《Hyperion: Building the Largest In-memory Search Tree》,2019年的一篇發表在SIGMOD上的論文,思想其實很簡單,在布局上比較講究,很精細。
圖1
1.Concept
1.1 Container
圖1右圖中的每個節點表示2B的Span,每個節點所表示的信息可以描述成如下,例如對于根節點的an,ki等于an,ki0等于a,ki1等于n。并且論文中將圖1右圖中的每個節點命名為Container,每個Container是一個最大fanout是65536的節點,如圖2。
圖2
1.2 T/S-Node

圖1右圖中每個節點的布局,采用了平鋪的方式,節點中無結構化信息,例如th和to,本應該是以t為父節點,h、o為子節點的結構,這種平鋪的方式比較浪費空間,th和to本可以前綴壓縮,只需要存儲一個t的。為了解決這個問題,在論文中,為了表達這種結構信息,作者使用了2種類型的Node,分別是T-Node和S-Node。例如對于圖2的C1,t是T-Node,h和o都是S-Node;對于C3,a和e都是T-Node,t是S-Node。實際上,分成2種節點的作用就是用來定界的,在節點內搜索的時候,能夠從一個T-Node節點跳到下一個T-Node節點。這里也可以看到T-Node中不需要指針指向每個S-Node的位置,而每個S-Node可能需要一個指針指向下一級Container的位置。
圖3
2.Physical Layout
2.1 Container Layout
Container在物理結構上按照緊湊型進行存儲,他的內部Node按照前序遍歷的方式順序排放,如下圖4。在他的Header中看到使用19bits表示Size,意味著Container最大占用空間512KB。支持2種leaf,分別是leaf with value以及leaf without value。我們最常見的是leaf with value,對于leaf without value,也就是對于KV來說,只有K沒有V。這個可能的場景例如RocksDB的刪除操作,只有Key,沒有Value。
圖4
先忽略Container的Header部分,我們來看下T/S-Node的內容,如圖5,這里也忽略了d、js、jt、c的內容,這些都是和優化有關。
1、宙斯:(羅馬又稱朱庇特)Zeus,天神之父,地上萬物的最高統治者,以貪花好色著名。2、赫拉:(羅馬又稱朱諾)Hera,宙斯的姐姐與妻子。是女性的代表,掌管婚姻和生育。性格特征是嫉妒。3、波塞冬:(羅馬又稱尼普東)。
圖5
在星際爭霸2,Hyperion號裝配了一系列小型炮,還配備了一個撞角。內部構造 Hyperion號內部環境舒適,燈光柔和,走廊寬敞。然而Hyperion號的防護措施并不像其他戰列巡洋艦一樣優秀。船上有很多開闊的樓梯,沒有門的過道等等,入侵。
Hyperion,從這個布局中可以看到,當在節點內進行搜索時,是一個遍歷的過程。例如要在圖5的C3中搜索e。第一步找到第一個T-Node a,比較發現不匹配。那么下一步就需要跳過a下面的所有子節點,但是節點中并沒有這個信息,因此需要一個節點接著一個節點進行遍歷,跳過所有S-Node,直到找到下一個T-Node e。這是一個非常低效的過程。
在Container中插入也是一個低效的過程,如圖6,需要將插入位置的原數據及其后面的所有數據后移,為插入位置騰出空間,需要進行大量的memmove操作。
圖6
引入和實施了元年費用控制系統,不僅實現了報銷填單控制、審批流程控制、預算控制、費用標準控制等多種功能,還實現了與周邊系統,包括OA系統(單點登錄)、HR系統(用戶同步)、影像系統(附件、圖片、影像共享)、Hyperion系統。
刪除過程同樣是一個低效的過程,如圖7,也需要進行大量的memmove操作。
圖7
2.2 Embeded Container Layout
Embeded Container是在子Container非常小的情況下,直接將子Container的內容放到其父Container中。如下圖8,C3的內容直接放在了C1中,此時,C1的h對應的S-Node將c標記置為10,從而感知到Embeded Container的存在。
圖8
圖9
2.3 Path Compression
Path Compression一般來說指的是路徑前綴壓縮,將相同前綴的部分壓縮掉。論文里面指的是后綴壓縮,將相同后綴的部分壓縮掉。之所有不用Embeded Container,是因為作者覺得這樣太低效了,有點大材小用。作者使用path-compressed node來表示被壓縮的后綴,S-Node中將c標記成11,從而感知到path-compressed node的存在。他的Header部分也只占用1B,其中7bits表示后綴長度,1bit表示后面有沒有Value(即該后綴直達Key的末端)。這也意味著最多能壓縮的后綴長度是128個。
3.Memory Management
Hyperion是一個緊湊型的Trie布局,這就導致了每在一個Container中進行插入,就需要重新分配一個更大的內存,將會引起嚴重的內存碎片。為了解決頻繁內存申請問題,同時也為了進一步降低指針的空間占用,作者設計了一套Hyperion自用的的內存管理算法。
圖10
如圖10,將Memory分成4個層次,最上面有64個Superbins,SB0負責大于2016B的Chunk分配(該塊內存將直接從heap上分配),SBi(1 <= i <= 63)分別負責32 * iB的Chunk 內存分配,每個Superbin中有16K個Metabins;第二層是Metabins,每個Metabin有256個Bins;第三層是Bins,每個Bin有4K個Chunks;最底層是Chunks,每個Chunk存儲一個Container。通過這樣的組織,可以將Hyperion中的指針空間降低到5B。
4.Optimization
4.1 Memory Optimization
為了更進一步降低內存占用,在論文中,作者使用了Delta Encoding技術。找一個基準Key,后面的Key只存儲delta值,不存儲實際Key,這就是T/S-Node中的占用3bits的d部分。如圖10的C3,a和e是兄弟節點,a作為基準Key,delta(a,e) = 101 - 97 = 4,3bits足夠可以表示,此時就不需要在e的S-Node中單獨再使用1B來存儲e了。而對于C3*,delta(e,t) = 116 - 101 = 15,超過了3bits的表示范圍,無法做Delta Encoding。T-Node的delta encode是通過兄弟T-Node來計算,S-Node的delta encode是通過兄弟S-Node來計算。因為Container中的Key也是順序存儲的,所以不存在負數的問題。而d的值非0,即說明只存儲了delta值。Delta Encoding技術對于順序或者說Dense Key場景下的內存縮減非常有用。
Moon(月球)、Phobos(火衛一)、Deimos(火衛二)、Io(木衛一)、Europe(木衛二)、Ganymede(木衛三)、Callisto(木衛四)、Mimas(土衛一)、Enceladus(土衛二)、Tethys(土衛三)、Dione(土衛四)、Rhea(土衛五)、Titan(土衛六)、Hyperion(土衛七)。
圖11
許配利翁(Hyperion):十二提坦之一,光明太陽之神。太陽,月亮和黎明之父。 提亞(Thea):十二提坦之一,寶物、光及視力女神;許配利翁之妻。 摩涅莫緒涅(Mnemosyne):十二提坦之一,詩歌女神(Musa)之一,記憶之神.宙斯第五位妻子九繆斯之母。
4.2 Search Optimization
前面說到,如果不用優化手段,在Container中查找就是一個順序搜索的過程,對于擁有最大可以達到65536這么大的fanout節點來說,這是一個非常低效的過程。搜索的過程可以分為2步,第一步定位到T-Node,第二步定位到S-Node。
4.2.1 Jump Successor
Jump Successor用來從一個T-Node直接跳到下一個T-Node,而不需要遍歷該T-Node下的S-Node,從而才能找到下一個T-Node的位置,對應著優化搜索第一步。若T-Node的js標記1說明使用了Jump Successor,此時該T-Node后面有一個16bits的reference,如圖11,存儲下一個T-Node距離該T-Node的距離。這是一個用空間換時間的做法,并且在插入和刪除過程中,可能還需要更新reference。
圖12
4.2.2 Jump Table

在前面的布局中,可以看到T-Node和Container中都有Jump Table標記,我們來分別看看他們的作用。
T-Node Jump Table
圖13
Container Jump Table
Container Jump Table也是為了快速定位T-Node,對應著優化搜索第一步。在Container的Header中,J占了3bits,最大表示7,每一個表示7個Entries,因此最多表示49個Entries。每個Entry占用4B,1B存儲T-Node的Key,3B的Offset用來定位T-Node的位置,這樣在搜索T-Node時,可以直接利用這個表定位到最接近目標T-Node的位置,最多再需要搜索256/49 = 6個T-Node即可以找到。
圖14
第一步,打開電腦,點擊smartview安裝包,進行安裝。請點擊輸入圖片描述 第二步,如圖所示,打開“Excel”,點擊“Hyperion”并進入。請點擊輸入圖片描述 第三步,如圖所示,點擊“Hyperion”之后,打開“connection”。請點擊輸。
4.3 Insertion & Deletion Optimization
每個Container占用的空間最大將超過400KB,在前面提到了Container中進行Insert和Delete需要進行繁重的memmove操作,這在大Container中將會引起非常嚴重的性能問題。作者通過將大Container分裂成多個小Container來緩解這個問題,在論文中,最多分裂成8個Container,那么第i個Container所負責的T-Node range是[32 * i,32 * (i + 1) - 1]。
圖15

sizec表示Container Size,論文中a = 16KB,b = 64KB。
版權聲明:本站文章均來源于網絡,如有侵權請聯系刪除!
