我們僅利用了列存儲文件格式的一半優勢嗎?

(*最初於2018年發佈在LinkedIn上)

列式文件格式已成為大數據系統的主要存儲選擇,但是當我本週末在Google上搜索相關主題時,我發現大多數文章都在談論特定列式格式與行格式之間的簡單查詢基準和存儲空間比較。 排序也是列格式的關鍵特徵,但是到目前為止,它的好處和有效實踐尚未得到強調或詳細解釋。 恕我直言,使用沒有適當排序的列格式似乎只佔基礎文件格式優點的一半。 我想分享我對該主題的見解。

互聯網和電子商務公司生成的日誌/跟蹤數據是大數據系統興起的主要原因,物聯網將把這種模式傳播到更廣泛的行業。 與高度規範化的數據模型相比,無需調用查找過程即可將維度屬性規範化為id或代理鍵,更容易生成此類日誌/跟蹤數據。 有時,數據模型非常寬泛,因此各種類型的記錄器可以生成相同的事件/日誌格式(以稀疏方式); 因此記錄器可以具有更簡單的代碼庫,並可以產生具有極高QPS / TPS的數據。 不久,此類數據的佔用空間已超過S3 / BigTable / HDFS上的數百PB。 然後,列式格式(Dremel / Parquet / ORC / Arrow / CarbonData)得到了拯救。

列格式的優點的前一半是:值按列聚簇,因此壓縮效率更高(以減少存儲空間),查詢引擎可以下推列投影(以減少網絡和磁盤的讀取I / O, 跳過不需要的列)。 優點的後半部分是:對行順序進行了適當排序,以將壓縮率推至新的水平,並且查詢引擎可以下推過濾謂詞(以減少讀取I / O)並應用矢量化計算。 您可能認為從壓縮的CSV / Avro轉換為Parquet / ORC應該已經實現了柱狀格式90%的好處,但是讓我說服您,對數據進行排序的開銷是絕對值得的。

我們僅利用了列存儲文件格式的一半優勢嗎?

這是一個案例來說明。 一個典型的網站日誌數據集包含:uuid,時間戳,user_id,cookie,user_agent,page_id,refering_site,http_header等。……讓我們對具有過濾器針對page_id的流行分析查詢進行基準測試:

· 文件系統上的原始Avro(壓縮壓縮)約為1.4TB; 查詢掃描整個1.4TB

· 簡單地轉換為ORC(zlib壓縮)約為0.9TB; 查詢掃描〜300GB

· 正確排序的ORC(zlib壓縮)約為0.5TB; 查詢掃描〜200MB

這類網站日誌通常以文本為中心且冗長,因此它們的大小過大(並激起了對大型基礎架構進行分析的渴望)。 在以上情況下,user_agent平均包含約200個字符(可容納40個整數列,),cookie約100個字符,page_id約40個字符。 為了節省大多數存儲空間,我們可以按3列的順序對行進行排序:user_agent,cookie,page_id。

· 將冗長的user_agent的重複值堆疊在一起,將獲得最小的編碼結果。

· 在同一個user_agent中,行進一步按cookie進行排序,因此user_id和ip_address自然排列,並且大多數重複值對齊。 現在,這三列的壓縮率均已優化。

· 下一個排序優先級是page_id,因為:

· page_id(例如電子商務中的product_id)是分析中最常用的過濾條件之一

· 網絡訪問高度偏向於相對較少的熱門page_id

從0.9TB壓縮到0.5TB的壓縮率提高了44%,而簡單的Avro到ORC轉換僅實現了(1.4–0.9)/1.4=35%的大小減小。 如果可以將篩選謂詞下推到文件讀取器,則除了對列進行修剪外,Presto / SparkSQL / Hive還可顯著減少從底層文件系統掃描的字節。 這就是為什麼使用過濾器WHERE page_id IN(?,?,?,…)的分析查詢可以跳過99%的數據塊的原因。 這表明直到您將最大的數據集縮小到其1/3大小之前,尚未收穫另一半優勢,並且您觀察到通過PPD(謂詞下推)相對於已排序的柱狀圖提供的令人難以置信的讀取時間I / O減少 文件。 PPD是現代計算引擎的重要功能。 您可以在其性能調整文檔中找到建議(以使用排序的列式文件格式),但是他們幾乎沒有詳細說明為什麼以及如何對數據進行排序。

您喜歡已排序的柱狀文件在存儲和性能方面的好處,對嗎? 但是排序是一項昂貴的操作,尤其是對於大量數據,因此您可能想知道這樣做是否負擔得起(這會導致數據提取過於繁重或危及SLA)。 以下是一些我認為可以分享的規則:

切勿對大型數據集應用全局排序(以優化列式文件的塊/索引布局)。 我們應該始終首先應用分片或範圍分區,然後僅對每個存儲桶/分區中的行進行排序。

以網絡日誌為例,我們可以嘗試以下策略之一:

· 首先按Cookie將每日流量劃分為n個存儲桶(只要每個存儲單元包含合理數量的記錄,n可以為128/256/512 /…),然後按user_agent,cookie,page_id對每個存儲桶進行排序

· 首先將每日流量分成兩個分區,一個分區用於訪客,另一個分區用於登錄的用戶。 然後按Cookie分行,然後按user_agent,cookie,page_id排序。 這是對第一個選項的擴展,如果很多查詢僅關注登錄用戶的活動,我們會進一步優化文件佈局

· 通過虛擬列hour_id = 00/01/02 /../ 23將每日流量分成24個每小時的分區,然後按user_agent,cookie,page_id對每個分區進行排序。 該策略在小時分區之間的數據分佈不均勻(與cookie分佈相比),但是如果應用了小時過濾,它可以很好地服務於查詢

· 將每日流量分成24個每小時的分區,然後按Cookie,ip_address,時間戳對每個分區進行排序。 這種策略不會像第1個第2個選項那樣積極地進行壓縮,但是通常相同的cookie也會導致相同的user_agent,因此總體壓縮效率仍然很高。 此策略不會為基於page_id的謂詞提供很多PPD好處,但是此選項非常適合會話化和渠道分析

以電子商務訂單表為例,您可以考慮:

· 按order_line_id將整個訂單表分成n個存儲桶,然後按order_line_id排序。 這是Hive ACID存儲表結構。 壓縮沒有進一步優化,但是它可以基於排序合併操作執行超快速連接和重複數據刪除,並可以通過order_line_id快速查找。

· 首先根據虛擬列order_date(從order_timestamp派生)對交易進行分區,然後按order_id或order_line_id將訂單分拆為n個存儲桶,最後按country_id,product_category_id,product_id和時間戳進行排序。 如果將country_id和product_category_id定義為分區列,則對於記錄數量很少的長尾國家/地區,您很容易遇到太多小分區的問題。 一旦在filter子句中使用了country_id和product_category_id,使用排序的列式文件就可以控制文件數量,但仍然提供有效的PPD。

以物聯網事件為例:

· 首先按日期,小時和主題進行分區,然後按device_id將事件劃分為n個存儲桶,並按event_type,subject,device_id和event_time進行排序。 由於subject和event_type是經常在filter和group by子句中使用的字符串,因此查詢可以受益於這種排序策略。

· 如果device_id導致偏斜,我們可以保留分區和排序配置,但切換到event_id / uuid作為分片列。

一般來說:

· 如果存在一個字符串列,該字符串列具有長且重複的值,則可以通過排序進一步壓縮

· 如果有一列具有中等基數(例如小於500K)並且經常在filter子句中使用(IN,BETWEEN,=,),我們可以通過優先排序此類列來支持PPD優化而不是更好的壓縮

· 如果有多個具有低至中基數的列並且所有列都頻繁出現在filter子句中,那麼我們可以首先對基數最小的列進行排序,然後對基數較大的列進行排序,然後對基數較大的列進行排序。

沒有一種萬能的排序策略,但是我們總是可以通過節省大量存儲空間和/或大大加快流行的查詢模式來證明排序的合理性。 無論如何,大多數大型數據集都需要經過壓縮或重複數據刪除過程,只要我們能夠正確分擔工作負載,額外的自定義排序開銷(每個分片)就不會很大。 最重要的是:如果生成數據文件,然後再讀取1000次或更多,則排序將為大型數據集釋放出柱狀格式的其他好處。

在我們整理分類的柱狀文件的注意事項之前,我想提到另一種增壓武器-矢量化。 大多數計算模式都會先將列數據塊旋轉回內存中的行,然後再處理這些行。 如果內存中的數據表示也是列式/矢量化的,許多分析和ML計算操作的速度可以提高10到100倍。 Dremio主要基於端到端的列式+矢量化。 Spark在2. +中添加了矢量化閱讀器和優化功能。 如果提供了排序的列輸入,則Hive和Presto可以執行矢量化連接和分組。 但是,由於行仍然是數據處理的主要內存格式,因此這些優化尚未得到廣泛關注和利用。

· 注意事項1:由於Parquet的普及,Spark / Hive比ORC具有更好的PPD和對Parquet的矢量化讀取支持。 您需要首先將嵌套數據結構展平為基本列,然後對ORC數據集進行排序。

Google Big Table + Big Query系統會根據最近的查詢模式在後臺不斷優化排序順序; Vertica可以將數據塊副本放入不同的排序順序,因此CBO可以選擇最佳副本來服務查詢。 Netezza和Redshift都對排序表進行了大量優化。 我希望這篇文章可以說服您在大數據系統中充分利用列式文件格式。

(*免責聲明:本文中表達的觀點僅為作者的觀點,並不反映作者的任何政策或立場。)

(本文翻譯自Eric Sun的文章《Are We Taking Only Half Of The Advantage Of Columnar File Format?》,參考:https://medium.com/@eric.sun_39815/are-we-taking-only-half-of-the-advantage-of-columnar-file-format-f1bae4927532)


分享到:


相關文章: