PAX:一個 Cache 友好高效的行列混存方案

今年,Spanner 終于發(fā)了另一篇 Paper Spanner: Becoming a SQL System,里面提到 Spanner 使用了一直新的存儲格式 - Ressi,用來支持 OLTP 和 OLAP。在 Ressi 里面,使用了 PAX 來組織數(shù)據(jù)。因為 TiDB 定位就是一個 HTAP 系統(tǒng),所以我也一直在思考在 TiKV 這層如何更好的存儲數(shù)據(jù),用來滿足 HTAP 的需要,既然 Spanner 使用了 PAX,那么就有研究的必要了。

PAX 的論文可以看看 Weaving Relations for Cache Performance 或者 Data Page Layouts for Relational Databases on Deep Memory Hierarchies

NSM and DSM

在談 PAX 之前,NSM 和 DSM 還是繞不開的話題,NSM 就是通常說的行存,對于現(xiàn)階段很多偏重 OLTP 的數(shù)據(jù),譬如 MySQL 等,都采用的這種方式存儲的數(shù)據(jù)。而 DSM,則是通常的說的列存,幾乎所有的 OLAP 系統(tǒng),都采用的這種方式來存儲的底層數(shù)據(jù)。

NSM.png

NSM 會將 record 依次在磁盤 page 里面存放,每個 page 的末尾會存放 record 的 offset,便于快速的定位到實際的 record。如果我們每次需要得到一行 record,或者 scan 所有 records,這種格式非常的高效。但如果我們的查詢,僅僅是要拿到 record 里面的一列數(shù)據(jù),譬如 select name from R where age < 40,那么對于每次 age 的遍歷,除了會將無用的其他數(shù)據(jù)一起讀入,每次讀取 record,都可能會引起 cache miss。

DSM.png

不同于 NSM,DSM 將數(shù)據(jù)按照不同的 attributes 分別存放到不同的 page 里面。對于上面只需要單獨根據(jù)某一個 attribute 進行查詢的情況,我們會直接讀出page,遍歷處理,這個對 cache 也是非常高效友好的。

但是,如果一個查詢會涉及到多個不同的 attributes,那么我們就可能需要多次 IO 來組合最終的 tuple。同時,對于寫入,DSM 因為會將不同的 attributes 對應的數(shù)據(jù)寫到不同的 page,也會造成較多的隨機 IO。

PAX

可以看到,NSM 和 DSM 都有各自的優(yōu)劣,所以如何將它們和優(yōu)點結合起來,就是現(xiàn)在很多 hybrid storage 包括 PAX 考慮的問題。

PAX 全稱是 Partition Attributes Across,它在 page 里面使用了一種 mini page 的方式,將 record 切到到不同的 mini page 里面。

PAX.png

假設有 n 個 attributes,PAX 就會將 page 分成 n 個 mini pages,然后將第一個 attribute 的放在第一個 mini page 上面,第二個放在第二個 mini page,以此類推。

page.png

在每個 page 的開頭,會存放每個 mini page 的 offset,mini page 對于 Fixed-length attribute 的數(shù)據(jù),會使用 F-minipage ,而對于 variable-length attribute 的數(shù)據(jù),則會使用 V-minipage。對于 F-minipage 來說,最后會有一個 bit vector 來存放 null value。而對于 V-minipage 來說,最后會保存每個每個 value 的在 mini page 里面的 offset。

可以看到,PAX 的格式其實是 NSM 和 DSM 的一種折中,當要依據(jù)某一列進行 scan 的時候,我們可以方便的在 mini page 里面順序掃描,充分利用 cache。而對于需要訪問多 attributes 得到最終 tuple 的時候,我們也僅僅是需要在同一個 page 里面的 mini page 之間讀取相關的數(shù)據(jù)。

Data Manipulation

Insert

當數(shù)據(jù)插入的時候,PAX 會首先生成一個新的 page,然后根據(jù) attribute 的 value size 分配好不同的 mini page, 這里需要注意下 variable-length value,因為它們的長度是不固定的,PAX 會使用一些 hint 來得到一個平均的 size。插入一個 record 的時候,PAX 會將這個 record 里面的數(shù)據(jù)分別 copy 到不同的 mini page 上面。如果一個 record 還能插入到這個 page,但這個 record 里面某一個 attribute 的數(shù)據(jù)不能插入到對應的 mini page 了,PAX 會重新調整不同 mini page 的 boundary。如果一個 page 已經 full 了,那么 PAX 就會重新分配一個 page。

Update

當數(shù)據(jù)更新的時候,PAX 會首先計算這個 record 需要更新的 attributes 在不同 mini page 里面的 offset,對于 variable-length value 來說,如果更新的數(shù)據(jù)大小超出了 mini page 可用空間,mini page 就會嘗試向周圍的 mini page 借一點空間。如果鄰居也沒有額外的空間了,那么這個 record 就會被移到新的 page 上面。

Delete

當數(shù)據(jù)刪除的時候,PAX 會在 page 最開始會維護一個 bitmap,用來標記刪除的數(shù)據(jù)。當刪除標記越來越多的時候,就可能會影響性能,因為會導致 mini page 里面出現(xiàn)很多 gap,并不能高效的利用 cache。所以 PAX 會定期去對文件重新組織。

小結

PAX 其實是一個原理比較簡單的東西,但它并沒有成為一個業(yè)界主流的存儲方案,應該有一些局限是我現(xiàn)在還不知道的。但既然 Spanner 敢用,證明在 HTAP 領域,PAX 也是一個可選擇的方案,對我們后續(xù) HTAP storage 的技術選型也有一定的指導作用。這里也就先記錄一下,也希望能跟這方面有經驗的同學多多交流下心得體會。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • TiDB 最初是作為一個分布式 OLTP 數(shù)據(jù)庫開發(fā)的,但隨著越來越多的用戶將其用于 AP 環(huán)境,并且給了我們很多...
    siddontang閱讀 3,742評論 1 12
  • 姓名: 李小娜 [嵌牛導讀] :當你在linux下頻繁存取文件后,物理內存會很快被用光,當程序結束后,內存不會被正...
    n184閱讀 4,007評論 0 1
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言,那么這個「動態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,351評論 0 7
  • 情景:子類繼承的父類分別在不同的module 當子類聲明和父類相同的方法名(A)時。在子類中調用父類的其他方法(B...
    GUGUCoder閱讀 465評論 0 0
  • 親愛的孩子,夜里總是忍不住又想念你了。離家數(shù)日,不能和你共享生活中的每一個時刻,雖說可以透過電話、視頻、短信、見面...
    卡卡2000閱讀 214評論 0 0

友情鏈接更多精彩內容