1. 程式人生 > >Apache Arrow原始碼分析(一)——簡介和框架

Apache Arrow原始碼分析(一)——簡介和框架

背景

列儲存在資料庫領域中早已被提出,列儲存資料結構在分析型事務上表現優異,大資料分析引擎,諸如Spark-SQL,Impala 均採用列儲存作為其中間資料表示形式,那麼Apache Arrow就是這樣一種記憶體列式資料結構。

在眾多分散式系統中,每個系統都有自己內部的記憶體格式,70-80%的CPU浪費在序列化和反序列化過程,類似功能在多個專案中實現,沒有一個標準。那麼Arrow就是為解決這一問題而提出了。Arrow基於列儲存的資料組織方式,能夠很好的適應CPU的Cache,以及現代CPU SIMD (Single input multiple data) 技術,並且提供良好的序列化和反序列化效能。更值得一提的是,Arrow提供良好的擴充套件性,既有C++版的實現,又有java版的實現,是一個很值得學習的資料結構庫。

基本思想

Arrow 基本思想就是把向量在記憶體中的佈局給緊湊話,說白了,就是把之前按行表示的資料按列進行組織。
這裡寫圖片描述

舉一個很簡單的例子,對於一個字串向量{“a”, “bb”, “”, “”, “ccc”},通常在c++中我們採用vector< string >進行儲存vector<string> strings = {"a", "bb", "", "", "ccc"};, 採用這種儲存方式,其記憶體佈局大致如下圖所示:
vector<string>記憶體佈局

由於STL容器string中儲存字串的空間在堆上分配,那麼每一個string物件會單獨在堆上申請記憶體空間,儲存字串,這就可能導致在記憶體中,vector< string > 儲存空間並非連續的。這樣的儲存會帶來兩個問題,其一在於,不能很好的適應CPU cache,其二在於序列化和反序列化代價較大。

那麼Apache Arrow將vector< string >進行變形,轉換成如下的儲存方式:
Arrow儲存

引入一個Offset向量,以及連續記憶體空間的buffer,對外提供和vector類似的介面。其中,對於string 的訪問介面實現如下所示:

  const uint8_t* GetValue(int64_t i, int64_t* out_length) const {                                                                
      int32_t pos = offsets_[i]; 
      *out_length = offsets_[i + 1
] - pos; return raw_bytes_ + pos; } std::string GetString(int64_t i) const { const uint8_t* str = GetValue(i, &nchars); return std::string(reinterpret_cast<const char*>(str), nchars); }

引入偏移量向量來對連續的buffer空間進行索引,從而對外提供和vector< string >類似的取值介面。

框架和類圖

Apache Arrow類的設計採用建造者模式,封裝了基礎類array,buffer,以及arraybuilder,具體類圖如下圖所示:

這裡寫圖片描述

參考資料: