金山雲團隊分享 | 5000字讀懂Presto如何與Alluxio搭配

語言: CN / TW / HK

導語

  • 金山雲-企業雲團隊(趙侃、李金輝)在交互查詢場景下對Presto與Alluxio相結合進行了一系列測試,並總結了一些Presto搭配Alluxio使用的建議。
  • 本次測試未使用對象存儲,計算引擎與存儲間的網絡延時也比較低。如果存儲IO耗時和網絡耗時較大時,Alluxio加速收益應會更明顯。

測試目的

  • 驗證影響Alluxio加速收益的各種因素
  • 記錄Alluxio在適宜條件下的加速表現
  • 總結Alluxio的使用建議

測試環境

集羣部署架構圖

  • 計算引擎使用Presto,數據源為Hive,Alluxio作為緩存。
  • 共搭建2個集羣:Presto+Alluxio集羣,Hadoop集羣。

Presto+Alluxio集羣配置

  • 機器:4台 linux虛擬機
  • cpu/內存:32核 64G
  • 磁盤:60GB SSD + 200GB SSD
  • 網絡:萬兆帶寬
  • 關鍵配置:

Hadoop集羣配置

  • 機器:5台 linux虛擬機
  • cpu/內存:16核 32G
  • 磁盤:60GB HDD + 1200GB HDD
  • 網絡:萬兆帶寬

測試用數據集列表

  • 測試使用的數據是tpc-ds標準數據集。
  • 因測試需要,我們導入了多份不同大小的數據集。每份數據集裏的表結構是完全相同的,區別是表中的數據量不同,部分表之間的分區也不相同。

Alluxio強悍的加速表現

首先我們來看看,當提供了相對適宜的條件,Alluxio的具體加速表現。

  • 以下查詢的數據集是tpc-ds數據集tpcds_bin_partitioned_orc_100,整個數據集的大小為23.4G。
  • 以下執行的SQL是在tpc-ds提供的sql中選取7條滿足條件的,實驗中對7條SQL各反覆查詢10次,記錄每次查詢的耗時。
  • 每次查詢之間間隔8~10秒,給Alluxio的異步緩存一定時間,儘量提高下一次查詢的命中率。

實驗結果展示

• 重點説明

○ 耗時的單位為ms。
○ “avg”列的值是第2次查詢至第10次查詢耗時的平均數。
○“first”列的值就是第1次查詢的耗時。“加速收益”列的計算方式是:(first - avg) / first。

實驗結果分析

  • 第一次查詢時,由於數據還沒有被緩存,耗時是最高的,往後數據逐漸被異步緩存入Alluxio,查詢耗時逐漸遞減,等全量數據進入Alluxio緩存,此時加速收益達到最高,查詢耗時最低且停止遞減。
  • 我們可以看到相較於耗時最大的first,avg的值有大幅度的降低,耗時僅有原來的20%~30%。從“加速收益”列來看可以更量化的評估加速收益。
  • 下面我們驗證一下關於影響Alluxio加速收益的具體因素。在下面的實驗中,可以看到Alluxio在更適宜的環境下,甚至可以把查詢耗時減少到原來的5%。

影響加速收益的重要因素

  • 根據測試的結果,結合官方文檔描述,總結出幾點因素會對Alluxio加速收益產生影響。下面我們就來看看這些因素
  • 重點説明:這裏説的Alluxio加速收益,指的是查詢的耗時在加速後比加速前快了多少,並不單單是指IO那部分的耗時快了多少。更具象化的描述,它指的是單個查詢在加速後的耗時比加速前降低了百分之多少。

因素一:查詢的Hive表的底層數據文件的大小和加速收益正相關

1. 結論:查詢的數據文件在小於約2MB時,文件越小,Alluxio加速收益越低。

因文件過小,所以每個文件是一個split。Presto解析每個split創建driver,調度driver執行,這段耗時是不能被加速的,而operator掃描的數據太小,那麼磁盤IO的耗時在整個耗時中佔比就會較低,Alluxio對查詢的加速收益就會降低。

在本次測試所使用的環境中,每個數據文件小於約50KB時,在查詢的整體耗時上,加速收益會比較低。

數據文件大於約2MB時,文件大小對加速收益的影響相對不那麼明顯。

這個2MB和50KB只是在本環境中觀察到的一個大概閾值,在不同環境中可能會有不同的表現。

2. 驗證:用一條簡單的SQL進行測試

【a. 實驗用例説明】

測試方法採用相同的SQL去查詢5個tpcds數據集中的同名表,保證SQL複雜度相同、表結構相同,分區表的分區數相同,僅僅是數據文件大小不同。

這裏用一條簡單的SQL語句反覆多次查詢,記錄每次查詢的耗時。

select * from web_sales where ws_wholesale_cost=1。where條件字段ws_wholesale_cost並不是分區字段,所以會觸發全表掃描。

在presto看到僅被劃分出2個stage

本次實驗查詢的web_sales表在5個數據集中的相關元數據

○ 對於分區表,由於數據文件較小,每個文件就是一個split。
○ 為了有更清晰的對比,也引入了非分區表的查詢,非分區表的數據文件數較少,每個數據文件大小均在100MB以上,Presto會按照HDFS文件塊大小來劃分split,每個split中的數據大概是28~38MB左右。

【b. 實驗結果展示】

【c. 實驗結果分析】

○ 當每個split的數據小於2MB時,加速收益會明顯低一些。數據越小,加速收益越低,split的數據達到幾十KB時,加速就很微弱了。
○ 我們看到當每個split的數據達到2MB時,加速收益和30MB的區別不大,説明數據大於2MB後,數據大小對加速的影響就不大了。
○ 下面我們換一條SQL、換一張表再驗證一次,可以看到結論是一樣的。

3. 驗證:用tpcds中的Query55進行測試

【a. 實驗用例説明】

query55中包含聚合、排序、大小表join,複雜度一般,presto會為其劃分7個stage

query55查詢的事實表為store_sales。

store_sales表的相關元數據

【b.實驗結果展示】

 

【c. 實驗結果分析】

○ 結論跟上一次實驗一致,當split的數據只有百來K的時候,加速收益比較微弱,僅20%。
○ split的數據大於2M以上,數據大小對加速收益的影響較小。

因素二:執行的SQL語句的複雜度和加速收益負相關

1. 結論:SQL語句越複雜,Alluxio的加速收益越低

SQL語句越複雜,計算的耗時就會越長,在整體耗時中,IO耗時的佔比就會下降,而Alluxio只能加速IO的耗時,所以在整體耗時的加速上,收益會降低。

在評估SQL複雜度時,我們可以參考Presto在執行SQL時劃分的Stage的數量,來量化SQL的複雜度,Stage越多則説明SQL相對複雜些。當然也可以肉眼大致判斷下複雜度:

a. 簡單:分組聚合、排序
b. 複雜:大小表join、select語句嵌套
c. 特別複雜:大表join大表、更多的表參與join、多個select語句嵌套

2. 驗證:針對store_sales事實表進行測試

a. 實驗用例説明】

測試方法:採用選取tpc-ds中查詢同一張事實表的不同query,去查詢同一個數據集。保證表結構相同、文件數相同、文件大小相同、分區數相同,僅僅SQL不同。

query中除了事實表還會查詢維度表,不同query涉及的維度表可能不同,但是維度表的數據量極小(比事實表小1000倍至1w倍),且都不是分區表,所以在這裏我們可以忽略維度表不同所帶來的影響。

測試時對同一條sql反覆執行,記錄每次執行的耗時。每次查詢之間間隔8~10秒。

以下測試數據集選擇tpcds_bin_partitioned_orc_100,事實表選擇store_sales。

store_sales表的相關元數據:

測試SQL採用如下6條

【b. 實驗結果展示】

【c. 實驗結果分析】

○ 我們看到最簡單的SQL,加速收益非常高。
○ 面對一般複雜的SQL,Alluxio也依然很好的加速收益。
○ 整體來看,Stage數量小於15時,Alluxio都有不錯的表現。

3. 驗證:當查詢的數據文件較小且SQL語句很複雜

【a. 實驗用例説明】

我們這裏再補充做一個實驗,當查詢的數據文件較小,而SQL語句又複雜的話,加速收益如何呢。

本實驗SQL語句使用query88,分別查詢2套數據集。

表的相關元數據

【b. 實驗結果展示】

【c. 實驗結果分析】

我們看到,在這種很不適宜Alluxio的條件下,加速收益會比較低。

因素三:查詢SQL語句返回的數據量的大小和加速收益負相關

1. 結論:查詢返回的數據量越大,Alluxio的加速收益越低

Presto最後會使用一個Driver來reduce所有Driver的計算結果,數據量越大,reduce的耗時越長,這裏主要包括計算的耗時和網絡IO耗時。如果是掃表時過濾的數據就很少,那麼參與計算的數據量就會增加,增加了計算耗時,那麼就降低了IO耗時在整個查詢耗時中的佔比

2. 驗證:

【a. 實驗用例説明】

我們使用2條簡單的SQL查詢同一張表,用where條件和limit控制一下返回的數據量

使用tpcds_bin_partitioned_orc_100中的web_sales表。

表的相關元數據

○ SQL1:select * from web_sales where ws_wholesale_cost=1- 返回的數據條數為7.35K,數據大小為2.12MB。
○ SQL2:select * from web_sales limit 2000000- 返回的數據條數為2M,數據大小為558.87MB。

【b. 實驗結果展示】

【c. 實驗結果分析】

○ 在返回少量數據時,查詢的整體耗時很短,加速收益非常好
○ 返回大量數據時,查詢的整體耗時大幅增加,加速收益不太好

因素四:影響加速收益的硬件環境因素

Alluxio的加速收益還受以下硬件因素影響:

• Alluxio緩存讀寫速度
• UFS磁盤讀寫速度
• 網絡帶寬

這部分結論就不做驗證了。

聲明:所有測試均在較為理想的環境下進行

  • 上述所有測試,都沒有考慮同時掃描的數據文件大小超過了Alluxio緩存的情況,在查詢時,數據可以被全量緩存,達到全部本地命中的效果。所以我們看到每次查詢耗時在經過2到4次查詢的遞減後,就會在一個很小的範圍內波動,總的來説耗時比較穩定。
  • 在生產環境可能會面臨很多查詢並行執行,需要掃描大量數據,數據文件的總大小會超過Alluxio緩存的大小。那麼就會觸發數據的淘汰,每個查詢都不可能緩存所有需要的數據,所以查詢的耗時永遠不會穩定,而是在一個較大的區間範圍去波動。
  • 本次測試沒有涵蓋數據文件存儲在對象存儲的場景。如果使用對象存儲S3,預計會有更顯著的加速效果。

關於Alluxio應用於生產業務的使用、優化建議

• Alluxio並不能在所有場景下都達到良好的加速收益,要發揮Alluxio更大的價值,我們總結了一些使用、優化建議。

建議一:使用Shadow Cache檢測Alluxio與生產上業務的貼合性

生產上引入Alluxio是否能帶來加速收益,應該設置多大的緩存容量能達到最大收益,需要有評估和檢測。

Alluxio提供了一個Shadow Cache功能,可以使用布隆過濾器記錄計算引擎訪問過哪些數據以及總數據量的大小。每次計算引擎訪問數據,都統計一次是否命中shadow cache中的數據。結合shadow cache和Alluxio的命中率可以檢測業務是否適合使用緩存。

○ 業務場景不適合使用緩存:統計shadow cache的命中率,如果較低,則説明業務場景中極少會訪問重複數據,那麼是不適合使用緩存的。
○ Alluxio緩存需要加大空間:如果shadow cache的命中率高,但Alluxio緩存的命中率低,説明業務場景適合使用緩存,但是當前Alluxio緩存的空間過小了。因為在數據文件被重複訪問時,之前存入Alluxio的緩存,已經因為緩存滿了而被淘汰了,所以重複訪問時將得不到任何加速。那麼此時加大Alluxio緩存空間會取得更好的加速收益。
○ Alluxio緩存的收益已經達到較佳值:如果shadow cache命中率高,Alluxio緩存的命中率也高,則説明目前Alluxio緩存帶給業務的加速收益已經達到良好水平,再加大Alluxio緩存空間意義不大。

使用Shadow Cache,對使用Alluxio在優化上有一個更直觀的方向指導。

建議二:預先加載熱數據

Alluxio的加速需要先把數據load到緩存中,這需要等待用户先訪問一次數據,也就是説第一次查詢是沒有加速收益的。那麼對於熱點數據,我們可以在用户訪問前就預先load到緩存中。對於長時間不會改變且熱點的數據,還可以把數據pin在緩存中,不會被淘汰。

建議三:動態判斷查詢是否需要被加速

有的查詢被Alluxio緩存可以帶來很好的加速收益,有的則不行。我們可以在查詢時動態的判斷是否需要讓Alluxio緩存。在查詢時,解析SQL語句得到查詢的表,先去拿到表的元數據,判斷數據文件大小,同時也結合SQL的大致複雜度,再決定查詢是否要走Alluxio。

建議四:設置單層緩存,使用SSD作為存儲介質

Alluxio官方建議不要設置多層緩存,數據在多層緩存中的下沉和上浮可能會對性能有些影響。出於成本和性能的綜合考慮,單層緩存的存儲介質建議使用SSD。

建議五:合併小文件

小文件過多會影響Alluxio的加速收益,可以對熱點數據,在查詢前先執行小文件的合併。Alluxio提供了這個功能,可以對Hive表同一分區下的所有文件進行合併,合併後的文件不會覆蓋原來的小文件,也不會更改Hive的元數據。當Alluxio要緩存這些小文件時,會直接緩存合併後的文件,大幅提升讀取速度。

想要獲取更多有趣有料的【活動信息】【技術文章】【大咖觀點】,請點擊關注 [Alluxio 智庫]