速度提升10倍,騰訊基於Iceberg的資料治理與優化實踐

語言: CN / TW / HK

分享嘉賓:蘇舒 騰訊 高階工程師

編輯整理:劉鵬鵬 滴滴出行

出品平臺:DataFunTalk

導讀: 本文主要介紹騰訊是如何基於Apache Iceberg進行資料的入湖、治理以及後面的一些優化。將從資料入湖、資料治理服務、資料查詢優化以及未來展望四個方面展開介紹。

01

資料入湖

本部分主要介紹Apache Iceberg基本概念以及結合Flink構建實時資料入湖鏈路。

1. Apache Iceberg是什麼?

iceberg其實就是在儲存和計算層之間的一個表格式,表格式的作用主要是對計算引擎提供一個訪問儲存層的介面,能夠提供一些ACID語義和MVCC的能力,以及像歷史回溯之類的功能。像傳統的Hive表都會帶一些partition或者是資料的格式、壓縮格式、目錄資訊等,但這些資訊都儲存在Hive Metastore裡,這裡也可以將Metastore理解為一種檔案的組織格式。從圖中可以看到,下層儲存層這塊是一個比較開放的儲存層,可以支援傳統的HDFS、物件儲存,檔案格式也是支援行和列。

2. Apache Iceberg的特性

  • 基於快照的讀寫分離和回溯

  • 流批統一的寫入和讀取

  • 不強繫結計算儲存引擎

  • ACID語義以及資料多版本

  • 表,模式及分割槽的變更

Iceberg很重要的一個特性是支援快照的讀寫分離回溯以及不繫結任何計算儲存引擎,可以方便使用者快速接入自己的儲存引擎,比如Spark、Flink或者Presto,在Iceberg上用的時候可以基於Iceberg的API做一些connector。還有一個很重要的功能就是支援ACID語義及資料多版本控制,並且也支援表、模式及分割槽的一個變更。這些功能對於後面我們來構建準實時的資料入湖是一些非常重要的特性。

3. Apache Iceberg檔案組織

圖中上層可以看到Commit的一個Timeline,Iceberg每次寫Commit操作都會生成一個新的Snapshot,比如snapshot-1其實是包含snapshot-0的所有資料,這裡可以想象我們平時用git的時候,git的每一次新的提交都包含之前提交的所有資訊,通過git log就可以看到,這裡我們也可以這麼理解snapshot的Timeline。下層是Iceberg基本的檔案組織格式,每一個manifest管理n個DataFiles,DataFiles在manifest記錄的是DataFiles的路徑資訊。通過這樣的一個檔案組織格式,在讀取的時候就可以很方便地做Commit TimeLine,比如說現在是11點,Commit的是Snapshot-1,如果想讀snapshot-0的話其實只需要指定Snapshot-id,就可以很方便的實現資料的回溯。

4. Apache Iceberg讀寫流程

接下來這個是在寫Iceberg的時候的一個簡單讀寫過程。從這個鏈路上我們可以看到每次Iceberg的寫操作,比如說正在寫第一個S1的時候是沒有辦法讀的,只有發生了Commit C之後S1才是可讀的,這個時候如果有n個執行緒同時在讀但有一些執行緒在寫的時候,可以做到只有commit完整的資料之後,對使用者的讀操作才能被使用者的讀執行緒所看到。這也是Iceberg裡面非常重要的特性,即讀寫分離。在對S4進行寫操作的時候,S3、S2、S1的讀操作是不受影響的,同時這個時候S4是沒有辦法讀得到的,只有Commit之後S4才能夠讀得到。Current Snapshot這時候就會指向S4,預設Iceberg讀的時候都是從最新的Current Snapshot開始讀Iceberg的資料。那麼如果要讀前面的資料其實就可以指定Snapshot的id去進行資料回溯的讀。

5. 增量讀取

我們前面知道Iceberg每個不同的Snapshot都包含了之前的所有資料,比如說像圖中S2是包含了S1的資料,在每次讀取的時候就可以指定S1之間的增量即紫色這部分的資料,不需要每次重複地讀全量的資料。增量資料在後面構建準實時的入湖鏈路是非常重要的,因為從構建一個Flink的job比如從Kafka寫入資料到Iceberg,寫入之後下游的任務可以繼續讀Iceberg,讀的時候就可以選擇增量的讀取,在整個鏈路上就可以實現實時的入湖鏈路。

6. Apache Iceberg Flink Sink

在Iceberg實時入湖的鏈路上我們用的是現在比較流行的實時計算Flink,我們知道上游InputStream是會源源不斷地往下游去寫的,如果在寫的時候不做多個併發寫的話對整個效能會有非常大的影響,因此把Iceberg Flink Sink拆成Writer和Commiter兩個部分。那麼為什麼只有一個Commiter呢?我們知道Iceberg的commit操作其實要到Hive MetaStore去獲得一個鎖,如果進行多個commit的話,每個commit都會到MetaStore獲取那個鎖,對MetaStore來說不管有多少commit操作都會進行排隊。所以這裡只有一個併發commit是為了讓Iceberg前面n個Writer所寫的資料一次性從不可見的狀態變成可見的狀態。其實到commit狀態的資料已經都到了儲存上了,只是現在的狀態是不可見,這對準實時的資料接入有非常大的幫助,比如說HDFS寫資料的時候需要在一個temp裡面把整個temp目錄move到可見的目錄上,這裡其實資料已經全部都寫到儲存上了,所做的操作僅僅是把它的狀態從原來的不可見狀態變成了可見的狀態,也就是前面我們所說的每個snapshot commit操作。

7. 近實時資料入湖

上圖是我們內部大量採用的Iceberg實時入湖的一個簡單鏈路。上游消費Kafka或者Binlog的資料,中間採用Flink將資料寫入到Iceberg,下游可以基於Iceberg基礎上繼續再接Flink去做一些ETL或者其他的操作,也可以直接在Iceberg的基礎上跑Spark或者Presto的一些任務。

8. 實時入湖平臺化建設

這塊是我們內部在整個實時入湖鏈路的基礎上為了方便使用者而構建的一個任務管理平臺,可以非常方便地幫助使用者去新建一個端到端的入湖任務,也可以看到一些任務執行的狀態。

02

資料治理服務

我們知道Flink任務跟傳統的任務不同的是,Flink任務是一個實時任務,實時任務的特點是常駐性,起了一個Flink任務就長時間執行,理想狀態下是不會中斷的。這種情況下,上游資料是源源不斷地進來的,Flink任務會源源不斷地進行Commit操作,如果對資料的實效性要求比較高的話,比如說Flink任務執行的時間是一分鐘、五分鐘或者是十分鐘級別。當運行了幾天或者是一兩個星期之後,在磁碟上發生Commit的次數就會非常地多,如果根據partition進行分割槽的話,磁碟上的檔案數量會膨脹的非常大。如果是傳統的批任務的話,跑完一批之後在後面再跑一次compaction任務進行compact。實時任務因為是不中斷的,所以就會遇到小檔案數量膨脹、元資料膨脹等的一些問題。

1. 實時資料入湖遇到的問題

我們知道實時任務為了保證實時性進行高頻的commit操作引起的小檔案數量以及元資料數目膨脹引起查詢效能的降低,還有資料本身缺乏生命週期管理。有時候寫很多的資料到HDFS上,一段時間就要根據實際業務場景的需求對過去的資料進行清理,比如清理掉兩個星期前的資料,這時候就需要額外的服務化平臺去幫助使用者去做這個事情。還有一點就是資料的實時寫入並不能夠根據使用者真實的查詢條件進行分佈,因為寫入只能根據寫入的條件去寫入,但是查詢條件比如說where或者過濾的條件可能是不一樣的,這個時候如果某些查詢經常頻繁發生的話,就會導致訪問這n個節點的查詢效能不太高,後面的服務也需要對資料做一個合理的重分佈。

2. 不合適的小檔案合併方案

我們在FlinkIcebergSink這邊嘗試了很多小檔案合併的方案。我們知道Flink Sink上游每次都會做commit操作告訴當前commit操作是commit到了哪個Snapshot,snapshot裡面增加了哪些檔案,這些檔案其實都是當前Snapshot裡面的。比如說真實的資料檔案在下游再接上一個operator的話,就可以對每次commit操作的檔案進行compaction的操作。這裡的rewrite也是同樣的道理,比如上游commit了90個檔案,假設rewrite分到了30個檔案,會對這30個檔案進行rewrite操作把這30個檔案rewrite成一個檔案,把檔案rewrite成一個檔案的時候就會把rewrite的檔案數量告訴下面的replace,replace知道當前的事物比如說新增30個rewrite,就會對30個rewrite檔案再次進行commit操作,也就是說replace和sink其實做的都是commit操作,只是replace commit的是rewrite的結果,而sink commit的是上游寫下來的資料。replace之後生成新的snapshot的檔案數量就是3而不是之前的90。這個合併方案我們之前也做過非常多的嘗試以及生產和測試環境的大量測試,實際證明這個其實是不合適的。因為下游所有的邏輯都是跟著Flink的任務走的,下游的不管是replace、rewrite或者是ScanTaskGen都要佔用Flink TaskManager的計算資源。在計算資源有限的情況下,在後面再接上任務的compaction寫一些任務的話都會大量的佔用整個叢集的計算資源。如果是同步的任務,下游的rewrite都會阻塞掉上游資料的輸入,假設把它改造成非同步的去跑後臺的執行緒,後臺的執行緒也要佔用task的計算資源,所以整體在生產上面通過觀察發現,每次如果rewrite操作的時候整個叢集主鏈路上的資料處理都會受到大大的影響,我們為了保證使用者對小檔案合併的透明,就想到了要提出一個完整的資料治理的服務。

3. 架構總覽

上圖是我們資料治理的整體架構,中間藍色的四個框是我們主要要做的業務邏輯,我們把資料治理服務主要分為四大塊,第一塊是Compaction Service,Compaction Service是為了解決小檔案過多的問題,我們知道Iceberg是讀寫分離的,我們可以對Iceberg實時鏈路上寫到磁碟上的一些小檔案進行非同步的compaction,這個compaction需要獨立的一部分計算資源。這樣的話,計算資源能夠幫助解決一些小檔案的問題,又不會影響到主鏈路上的資料。Compaction Service服務會定期的根據Iceberg上游的表決定進行多大力度的合併,比方說檔案合併的target是128M,每個snapshot檔案數量是n,那就會根據這樣的數值去判斷當前的Iceberg寫入snapshot裡面這些值的狀態是多少,以此決定要不要去觸發非同步檔案compaction的操作。Expiration Service是為了定期清理snapshot,比如說現在的snapshot裡面的檔案是1、2、3,合併之後的檔案假設是1+2+3=6,我們知道6其實是包含1、2、3的一些資料,那麼現在6的snapshot的資料就跟1、2、3的snapshot資料是重複的,在磁碟上是存在Double的資料,這個時候就需要定期的跑snapshot把合併之前的那些snapshot資料進行定期的清理操作,刪除一些冗餘的資料可以大大的減少儲存壓力。第三個就是Clustering Service,對某些查詢比較頻繁的操作可以通過Clustering  Service進行資料的重分佈,比如說根據某些查詢的列進行資料的一些聚合,這樣的話在某些查詢經常發生時儘可能避免掃描過多的檔案,對查詢的效能會有極大的提升。最後是Cleaning Service,針對某些使用者會有一些對過去資料的清理操作,後臺會有一個Service根據使用者會去配置表裡,比如說配置表裡面的TTL是3天或者30天,Cleaning Service就會定期地根據使用者配置的去清理這些過期的資料,這點比較類似kafka,kafka也有一些類似資料超時的機制。

4. 總體流程

上圖是整體資料的流程,可以看到Compaction整個服務中的資料流。我們先從Compaction服務來簡單的介紹,比如說使用者對Iceberg進行操作,我們在Iceberg介面這邊已經為Iceberg實現了Iceberg的Metrics彙報到外接系統的功能,首先Metrics的Reporter會將Iceberg的一些建表、刪除、更新或者任何Commit操作所產生的snapshot建立snapshot的summery彙報到iceberg的Metrics Event Handler那邊,Metrics Event Handler接收到不同的事件之後會根據不同事件的型別將這些事件儲存到MySQL。這裡我們做了一個改造採用一個訊息佇列來保證事件的時效性,並且對訊息佇列裡面的資料定期的儲存在CheckPoint中。我們知道表其實是有兩種狀態,DDL狀態或者DML狀態,表的一些基礎的記錄資訊比如表在compact之前/後的檔案數量、以及表的檔案數、操作的型別比如新建、commit、delete這些表所能提供的一些metrics資訊,當資料通過訊息佇列傳送到中間階段的時候,中間階段內部有個規則管理器會去配置大量的規則,比如一些使用者希望表在每產生100個10M檔案的時候就進行一次合併。這些規則的介面其實是開放給使用者去配置的,這些介面配置之後會將配置傳給下游的任務排程器,任務讀取器會讀取上游傳送過來的一些規則,以決定現在要根據這些規則去起一個什麼樣的任務。圖中我們可以看到下游會有很多不同的任務,比如JOB1、JOB2、JOB3這些任務目前是採用離線的Spark任務去跑上游傳送過來的資訊。執行的頻率有5分鐘、10分鐘和60分鐘,主要就是根據使用者所配置的表。使用者的表裡面如果要保留過去100個檔案,這個時候在監控裡面看到使用者會一直頻繁地在提交,那麼在單位時間內所產生的檔案數量會非常非常的多,這個時候就需要更低的頻率比如5分鐘去對使用者的表執行一次compact操作。有些使用者比是10分鐘或者20分鐘才commit一次,這個時候可能只需要跑小時級別或者跑5個小時排程一次去做這個檔案的處理,這邊是針對不同使用者的表的一些metrics的情況來決定應該將使用者的表放給哪一個粒度的排程任務去執行。那麼我們知道每個job可以看到很多使用者的表,一個job可能會處理三四個表,每次處理完之後會將這三四個表的處理邏輯通過Metrics System訊息佇列再反饋給剛剛我們記錄的MySQL,然後再通過Grafana或者一些監控的工具就可以看到整個任務的compaction的執行情況,包括compact之後表是什麼狀態這裡都可以看得到。還有一個記錄重要的點是每次compact的表任務執行的過程中花了多少時間,這樣就可以通過Job Handler動態地調整每個Job所負責的表的數量,比方說一個job執行的表是1、2、3三個表,發現1表跟2表執行compact任務花了10秒鐘就執行完了,3表執行了5分鐘,因為整個任務是併發提交的,所以需要等到第三個表執行完之後這個任務才能夠繼續排程下一次。這個時候就可以在下次排程的時候把3表排程到其他的任務區,1表就可以在一分鐘之內進行不斷地做檔案數量的處理。

5. 實踐效果

對於使用者來說要使用compaction服務其實是非常簡單的,只需要建立一個表然後在表裡面配置檔案處理的引數,圖中表示的是snapshot保留過去10分鐘的snapshot,或者是過去10個snapshot的數量,metadata的檔案儲存過去10個metadata檔案,每新產生5個snapshot就觸發一次rewrite操作。這個時候使用者只需要去配置後端的 metrics的彙報和檔案的compaction以及檔案的一些expiration,這些所有的動作在這個時候全部對使用者是透明的,使用者只需要去配置這個表,後面我們的服務都會自動地幫使用者去做好。

接下來可以看到整體的資料檔案和meta檔案數量,根據剛剛我們配置的值,如果在長時間執行compaction之後是能夠控制在一個比較合理的範圍。我們可以看到下面meta資料夾裡面放的其實是iceberg的meta資訊,包括像m0、avro這些都是snapshot的資訊。上層的parquet是真實的資料檔案,我們可以看到第二位有140、269、286這些的檔案其實都是執行的compact之後的rewrite之後的檔案。

03

資料查詢優化

從剛剛這個合併裡面我們可以知道,在做rewrite的時候只是把這些檔案進行簡單的重寫,比方說將三個檔案寫成一個檔案,對整個的查詢效能其實是已經能夠得到一定的提升,因為相當於掃描的檔案數量得到大大的降低,但是如果說真的要對某些頻繁發生的查詢效能進一步優化的話,這樣是遠遠不夠的。所以我們接下去會介紹我們在資料查詢優化方面所做的一些工作,首先介紹基於空間曲線演算法優化iceberg的資料查詢效率。

1. 空間填充曲線簡介

首先介紹一下什麼是空間查詢曲線?

在數學分析裡面,空間填充曲線是一個引數化的組合函式,會將單位區間內的區間對映到單位的正方形或者立方體中。比如說在一個二維的空間裡,可以通過一維的一條曲線穿過這個空間裡面的每一個點,直到填充滿整個二維的空間平面,如果曲線所填充的粒度越來越密的話,其實整個二維平面會被填充滿,這個是數學的一個重要特性。查詢優化這塊其實就是基於這樣的特性,我們可以看到空間填充曲線的話,因為在二維平面裡面它經過了二維平面的每一個點所以我們就可以將整個二維平面的空間降成一維,將多維的一個空間點轉化成一維對於後面的資料查詢優化演算法是非常大的幫助,今天我們講的一個重點其實是利用了圖中第四個Z-Order的演算法。

2. GeoHash演算法介紹

我們知道GeoHash演算法就是基於Geo的特性來做的,我們可以看到圖中GeoHash演算法其實是一個地理位置編碼將空間分成一個網格,在網格中可以定位某一些點以及哪些點離這個點最近。這個演算法常用的一個場景是點評、外賣檢視附近有多少外賣商家。從圖中我們可以看到,對於生成一個z order地址來說,比如說黑色的虛線所畫的這塊,四個地址我們就可以認為是靠的比較近的。一個點附近hash字串如果字首是一樣的我們就認為它的點是靠的比較近的,我們可以看到每個虛線框裡面的字首都是100,通過這樣的一個z地址可以把二維平面裡面的資料進行降維,可以讓降維之後的距離變得比較近,通過這種演算法我們就可以很方便的進行多維資料的聚合操作。

3. 為什麼需要多維資料聚合

我們知道在N列數排序的時候比如order by FirstName,第一列的效果往往是比較好的,越往後可能效果會越差,到n列之後整個資料可能就是離散的。如果查詢條件比較多的情況下,檔案過濾效果是比較差的,因為可能需要掃描表的所有資料才能去讀。資料如果呈現自然聚集的話會有幾個特點,比如單調遞增的id或者其他根據資料寫入的時間或是寫入前對資料進行的排序,這在這個例子中可以看到越往後幾列資料越亂。

4. Iceberg表多維聚合

同理,我們在iceberg表中間做多維聚合時,首先將不同的snapshot的檔案進行合併寫入小檔案,然後進行optimize優化資料的分佈,其實就是剛剛我們說的基於z order演算法。我們將原先分散在叢集中不同地方的檔案進行重分佈,這樣在查詢的時候只需要根據查詢optimize之後的結果檔案就可以了。在這個例子中綠色的點可以理解為是符合過濾條件的,紅色是不符合過濾條件的,過濾條件指的是在做where的時候的過濾條件。可以看到在Snapshot N的時候資料是處於上游寫入的狀態,在第二個階段的時候進行optimize的時候可能是第一次進行optimize操作它的strategy是all需要掃描所有的檔案,這個時候不符合過濾條件的都被聚集到m1和m4,m1、m4裡面都是紅點不符合聚合條件。當然它也不能保證所有的紅點都scan到某些檔案,因為資料要保證相同的過濾條件儘可能的聚集在一個檔案裡。在第二個階段比如說這個時候會在第一次進行optimize之後還會進行一次寫,因為上游只要是實時的就會不斷的往Snapshot裡面寫入資料,比如f2001到f3000這一段寫了n個數據檔案,在Snapshot N+3階段執行的是incremental的optimize就只去優化新寫入的這些檔案,經過這樣的操作之後,檔案的數量會大大的減少,在查詢的時候就可以避免非常多的沒有用的檔案掃描操作。

我們在圖中可以看到,在Spark sql這邊其實是支援這樣的一個語法,比如說在optimize table employee zorder by first_name, last_name,我們假設first_name和last_name是二維的,因為是兩個欄位其實就是二維的。首先根據first_name和last_name會先計算它的分割槽id,計算的規則目前我們實現的是一個固定的partition值,然後將這個分割槽id轉換成一個二進位制,然後基於GEOHash演算法。這裡可以看到是交錯位去生成z地址的,Thomas 0放奇數位,More 0放偶數位,以奇偶交錯的方式生成z地址。這樣生成z地址可以看到Thomas More和Thomas Alva Edison以及Melisa Kort在第二列的排序都不是有序的。經過ZOrder之後字首都是16個0,這時候就可以將這幾個聚合在一個檔案裡。當根據FirstName或者LastName進行查詢的時候就可以很方便的根據ZOrder的地址進行查詢操作避免其他檔案的掃描。可以看到它其實是根據多維Column生成Z地址,從f2到f1000的資料先根據裡面的資料進行線性掃描,掃描生成一次地址,生成地址之後,接下來要做的一個很重要的事情就是Repartition。

根據Z地址進行Range重分割槽,因為只有根據Z地址進行Range重分割槽之後我們才能夠將原先分佈在不同的點的資料的檔案聚合到同一個點上。比如根據Z地址重分割槽之後可能生成了兩個partition,在查詢的時候就必須對資料進行寫回儲存。repartition之後要進行一個重寫操作,重寫之後生成一個新的snapshot N+1,這個過程也就是剛剛S N到S N+1的一箇中間發生的詳細的過程。

經過事物回寫儲存之後,在查詢的時候就根據where條件智慧掃描m1和m3的資料,因為m2裡面都是紅點不符合查詢的條件。

5. 查詢效能優化評測

經過我們的優化之後,可以看到圖底部有條select語句計算一個簡單的count,根據first_name和last_name進行過濾。上部分是在沒有優化之前在HDFS上和優化之後的效能對比,可以看到效能差距是非常大的,效能優化的一個主要的點就是把大量的小檔案掃描的時間優化了。

04

未來展望

Iceberg核心及資料湖平臺化的工作規劃

1. Iceberg核心能力

進一步優化索引系統,提升查詢效能。 前面說到我們對查詢效能進行了zorder索引系統的構建以提升查詢的效能。但是zorder是有一定的侷限性的,它需要根據查詢條件去進行re-clusting,如果查詢條件發生變化的話需要重新計算。另一個是如果查詢條件特別多達到幾十個或者上百個的話,zorder會面臨維度膨脹的問題,計算出來的z地址會非常的長。這一點我們後面會根據不同的場景需求進行不同的索引來儘量避免過多的檔案掃描以及使用zorder沒有解決的一些問題。

增量讀取能力的增強,MOR方式入湖。 我們知道現在的增量讀取是每次讀取的是incremental的snapshot,但這個時候如果發生replace操作的話,產生的rewrite之後的snapshot在這裡的增量讀取整個語義目前是沒有很好的定義的,我們是希望在引擎層通過skip以及通過記錄rewrite之前的一些meta資訊來解決這個問題,這塊的話也是我們下一步的一個任務的規劃。

SQL能力的增強。 使用者可能很希望只通過一些SQL就能夠執行一些任務,比如使用者通過我們的平臺化建表,我們可以將這個表很方便地納入平臺的管理上,使用者自己建的表如果我們沒有辦法check到的話,也是需要提供一些SQL增強的能力,方便使用者更好的去執行使用iceberg過程中遇到的一些資料管理問題。

2. 資料湖平臺化建設

持續迭代資料治理服務平臺。 我們會持續迭代資料治理服務化平臺,包括如何更好地去執行小檔案合併的策略,包括怎麼樣儘量避免重複的小檔案的rewrite操作,已經重寫了的小檔案什麼時候將它合併到我應該要被寫的檔案列表裡,這些都是需要在後面不斷地迭代中去不斷地優化。

統一的元資料管理,元資料發現。 對於使用者來說,因為資料湖本身是寫後schema的模式,所以使用者其實並不希望資料只是上傳了CSV或者JSON這樣的原始資料對於裡面的schema其實可能並不知道,希望平臺能夠幫助他發現這些schema,這一塊也是平臺化建設中後面不斷地去優化的內容。

與更多資料系統打通,構建入湖+分析平臺。 比如說資料已經寫入iceberg裡面去了,可能會在上面繼續構建一些分析型的任務,比如更好地去優化presto的查詢效能,或者去進行平臺化構建更多分析型的任務,比如spark或者flink的批任務,這塊會跟更多的計算引擎去打通,更方便使用者使用從端到端,從入湖到分析的整個的一個鏈路平臺。

05

問答環節

Q:iceberg的zorder有計劃提交到社群嗎?

A:我們現在是把剩下的一些測試和優化進一步做完善之後,後續有計劃反饋給社群。

Q:zorder優化是針對大量小檔案場景下的優化嗎?

A:zorder優化的場景是某些經常發生的查詢,查詢條件相對固定這種情況下為了提升查詢的效能會用zorder的演算法根據查詢的條件將資料進行重新的分佈。小檔案就是剛剛講到的上面會有一個compaction先將檔案進行一個合併,然後zorder對資料進行重分佈,以此來提升整個的查詢效能。

Q:也就是說小檔案不多的時候效果也是很好的嗎?

A:是的。

Q:hive全量歷史資料的遷移入湖有相關的支援方案嗎?

A:這塊我們內部構建的一個平臺上其實是已經有相應的任務,比如執行了一個hive的一個入庫,從hive表匯入到iceberg表的鏈路上,內部其實是會有平臺化上面會取一些類似於像spark導數任務去做這樣的事情。

Q:需要把hive的全量導數這部分全量讀一遍,然後才能入湖嗎?

A:現在我們是這麼做的,就是spark導數。

Q:Clustering service是通過資料的冗餘儲存,把資料以其他的column做partition或bucket或sort來提高file proning的效果嗎?

A:clustering就剛剛我們說的,它其實根據的是Column,比如說查詢的話是根據Column就是我會將這個column的資料在某些經常發生的一些查詢的條件的column資料會把它聚合在同一個檔案裡面去,其實在iceberg上這個階段如果說針對clustering資料生成新的snapshot,針對去讀snapshot的時候就會讀到下面clustering之後的一些檔案。如果說是擔心資料冗餘的話,因為bean重新生成後的資料檔案肯定是需要通過snapshot對外暴露的,可以去跑一些資料定期清理的一些動作去完成這個事情。

今天的分享就到這裡,謝謝大家。

分享嘉賓: