天天看點

EMR Spark Relational Cache 利用資料預組織加速查詢背景存儲格式資料分區檔案索引資料排序小結

作者:

王道遠,花名健身,阿裡雲EMR技術專家,Apache Spark活躍貢獻者,主要關注大資料計算優化相關工作。

Relational Cache相關文章連結:

使用Relational Cache加速EMR Spark資料分析 使用EMR Spark Relational Cache跨叢集同步資料 EMR Spark Relational Cache的執行計劃重寫 EMR Spark Relational Cache如何支援雪花模型中的關聯比對

背景

在利用Relational Cache進行查詢優化時,我們需要通過預計算,存儲大量資料。而在查詢時,我們真正需要讀取的資料量也許并不大。為了能讓查詢實作秒級響應,這就涉及到優化從大量資料中快速定位所需資料的場景。本文介紹在EMR Spark Relational Cache中,我們如何針對這種場景進行了優化。

存儲格式

在資料存儲格式上,我們預設選擇Spark社群支援最好的Parquet格式。Parquet是一種列式存儲格式,我們可以很友善地利用列式存儲格式進行字段裁剪。另外,Parquet的每個資料檔案由多個Row Group組成,同時在每個資料檔案的footer中記錄了各個Row Group的統計資訊,如最大值、最小值等。這些統計資訊可以在讀取資料時減少實際的IO開銷。事實上,在現在的Spark版本中,我們可以看到Catalyst優化器已經把可以下推的一些過濾條件下推到了Parquet reader,利用Parquet檔案的統計資訊過濾真正需要讀取的Row Group,進而實作減少IO量,加速查詢時間的效果。這也是列存格式基本都支援的功能。

對于Relational Cache而言,有很多過濾條件時确定已知的。我們直接利用這一特性,将确定的查詢條件下推到Parquet reader裡,由Parquet reader完成對Row Group的選擇。由于實際要讀取的資料量占總資料量的比重往往很小,這種過濾的實際效果還是比較好的。

EMR Spark Relational Cache 利用資料預組織加速查詢背景存儲格式資料分區檔案索引資料排序小結

資料分區

對于Spark Relational Cache來說,由于建構Cube時會使用到Expand算子,我們需要引入Grouping ID來區分不同的grouping set。在大部分後續的查詢中,我們往往隻需要其中一個Grouping ID所對應的資料。是以,Grouping ID成了一個天然的資料分區選擇。在Hive/Spark等大資料分析引擎中,資料分區是對于結構化資料,将其中一個或多個字段的具體值作為目錄,分目錄存放檔案的一種常見做法。當我們确定要選擇某Grouping ID對應的資料時,我們隻需讀取對應目錄中的資料即可。這種做法可以直接忽略Grouping ID不比對的檔案,進而大大減少啟動的總task數量,減少Spark的任務排程開銷。

檔案索引

當總資料量較大時,存儲的檔案數也會比較多。此時即使我們通過Parquet的footer可以獲得較好的過濾效果,我們還是要啟動一些task去讀取這些footer。在Spark實際的實作中,往往需要與檔案數量的量級相當的task去進行footer讀取。在叢集計算資源有限時,排程這些任務就顯得比較浪費時間。為了能進一步減少Spark作業的排程開銷,進一步提高執行效率,我們實作了檔案索引來優化這種場景。

檔案索引就類似于獨立的footer。我們提前收集每個檔案中各字段資料的最大最小值,并存儲在一個隐藏的資料表中。這樣,我們隻需要讀取一個單獨的表就可以從檔案層面對需要處理的檔案做一個初步的過濾。這是一個單獨的stage,由于一個檔案隻對應這個隐藏表中的一條記錄,是以讀取隐藏表所需的task數量要遠遠小于讀取所有資料檔案footer的開銷。後續stage的任務數量也是以可以大大減少。在Relational Cache的通路場景下,整體加速效果非常明顯。

資料排序

為了能實作高效的資料準備過程,不論是在Parquet檔案的footer還是在我們實作的檔案索引中,都是主要依靠最大值和最小值的資訊來過濾資料。那麼在極端場景下,光靠這些統計資訊可能會完全沒有過濾的效果。舉個例子,如果某個key的所有資料檔案、所有Row Group的最大值和最小值都等于全局最大值和最小值時,對這個key的過濾就完全無效了。這樣,我們會自然而然的想到對資料進行排序。

但是,傳統的資料排序還有一個問題。在資料庫中,當我們對多個字段進行排序時,往往字段之間具有主次關系,這就導緻排序字段序列中,排在最前面的字段有很好的過濾效果,而排得靠後的字段因為資料分散,往往過濾效果越來越差。這就需要我們找到更好的排序方法,能夠兼顧到多個字段的資料過濾效果。

這裡涉及到一個空間填充曲線的概念。我們可以把資料想像成一個有限空間,如何将資料進行排序和分塊,能夠使得每一塊的最值都隻是在一個不大的範圍内,進而讓檔案索引獲得較好的過濾效果呢?我們選擇了Z-Order曲線對多元資料空間進行排序,這樣可以保證每列都有較為均衡的過濾效果。下圖是二維空間中Z-Order曲線的示意圖。

EMR Spark Relational Cache 利用資料預組織加速查詢背景存儲格式資料分區檔案索引資料排序小結

不過我們也要注意到,随着排序列的增加,單列的過濾效果将會越來越差。是以在實際運用中,我們也要對排序列進行取舍,才能獲得最佳的整體效果。

小結

本文介紹了EMR Spark的Relational Cache如何從資料量較大的Cube中快速提取出所需資料加速查詢的原理。通過列式存儲、檔案索引、Z-Order等技術,我們可以快速過濾資料,大大減少實際發生的IO資料量,避免IO瓶頸的出現,進而優化整體查詢性能。

參考

Apache Parquet Processing Petabytes of Data in Seconds with Databricks Delta Z-Order Curve
EMR Spark Relational Cache 利用資料預組織加速查詢背景存儲格式資料分區檔案索引資料排序小結

繼續閱讀