基於iceberg的master分支的9b6b5e0d2(2022-2-9)。
參數說明
1、PARTIAL_PROGRESS_ENABLED(partial-progress.enabled)
默認為 false。該參數能夠讓合並任務以group為單位做提交,當其中一個group任務失敗,可以單獨對該group任務重試。
2、USE_STARTING_SEQUENCE_NUMBER(use-starting-sequence-number)
默認為 true。
該參數使用做合並時的sequenceNumber作為新的數據文件的sequenceNumber。
測試
一、append方式生成 a,b,c三個snapshot,基於b做文件合並。
模擬的場景是:已存在a,b快照,現在基於b快照做小文件合並,但任務還未完成時,另一條數據流基於b快照做了append類型的數據:
右:USE_STARTING_SEQUENCE_NUMBER,下:PARTIAL_PROGRESS_ENABLED | true | false |
---|---|---|
true | 成功 | 成功 |
false | 成功 | 成功 |
-
成功:生成新的快照,最終snapshot是 a,b,c,d。
-
新生成的大文件是基於a,b的數據文件的總和,
-
快照d中包含了c的數據,以及基於a,b合並的數據。
-
a,b,c,d對應的squenceNumber分別是1,2,3,4:
USE_STARTING_SEQUENCE_NUMBER 為 true時,d里面生成的新的大文件對應的manifest的squeceid是用的以前的2,刪除的manifest用的是新的id4
USE_STARTING_SEQUENCE_NUMBER 為 false 時,d里面合並任務使用的全都是最新的id
結論:
1、純append流的數據,做小文件合並都能成功。
2、可以通過設置 USE_STARTING_SEQUENCE_NUMBER 字段來控制合並任務中的manifest的squencyNumber。
二、append方式生成 a,b,c 三個 snapshot,先基於c做一次合並,合並成功后,基於c再做一次合並。
模擬的場景是,基於c快照做小文件合並,該任務還未完成,又啟動了一個基於c快照做小文件合並的任務:
右:USE_STARTING_SEQUENCE_NUMBER,下:PARTIAL_PROGRESS_ENABLED | true | false |
---|---|---|
true | 成功,但沒生成新快照 | 成功,但沒生成新快照 |
false | 失敗 | 失敗 |
- 成功,但沒生成新快照:只是表示該任務是完整執行了,沒有出現異常退出的情況,但最終並未生成新的快照。PARTIAL_PROGRESS_ENABLED 設置 true,會打印出異常信息,但由於是部分提交,這些異常被忽略,最終程序執行成功,但也沒有生成新的 snapshot。Failure during rewrite commit process, partial progress enabled. Ignoring。
- 失敗:提示 Cannot commit rewrite because of a ValidationException or CommitFailedException. This usually means that this rewrite has conflicted with another concurrent Iceberg operation. To reduce the likelihood of conflicts, set partial-progress.enabled which will break up the rewrite into multiple smaller commits controlled by partial-progress.max-commits. Separate smaller rewrite commits can succeed independently while any commits that conflict with another Iceberg operation will be ignored. This mode will create additional snapshots in the table history, one for each commit.
結論:目前功能上不能基於同一個快照做多次合並,只會成功一次。
三、append方式生成 a,b 兩個snapshot,對a的數據做更新生成c,再基於b做文件合並。
模擬的場景是:基於b快照做合並,此時還未完成,另一條數據流對a快照中的數據做了更新,且提交成功生成了c快照:
右:USE_STARTING_SEQUENCE_NUMBER,下:PARTIAL_PROGRESS_ENABLED | true | false |
---|---|---|
true | 成功 | 成功,但沒生成新快照 |
false | 成功 | 失敗 |
- 失敗:提示 Cannot commit, found new delete for replaced data file。
- 成功,生成最新快照d,生成快照a,b中數據合並的大文件
- 成功,但沒生成新的快照:參考上面說明
結論:在合並的過程中,有另一條數據流對需要合並的數據做修改,可以通過設置 USE_STARTING_SEQUENCE_NUMBER 來使任務成功。
四、append方式生成 a,b,c 三個snapshot,對c的數據做更新生成d,再基於b做文件合並。
模擬的場景:基於b快照做合並,此時還未完成,另一條數據流先做append,生成了c快照,然后又對c快照里的數據做修改生成了快照d:
右:USE_STARTING_SEQUENCE_NUMBER,下:PARTIAL_PROGRESS_ENABLED | true | false |
---|---|---|
true | 成功 | 成功,但沒生成新快照 |
false | 成功 | 失敗 |
- 失敗,提示:
Cannot commit, found new delete for replaced data file
Cannot commit rewrite because of a ValidationException or CommitFailedException. This usually means that this rewrite has conflicted with another concurrent Iceberg operation. To reduce the likelihood of conflicts, set partial-progress.enabled which will break up the rewrite into multiple smaller commits controlled by partial-progress.max-commits. Separate smaller rewrite commits can succeed independently while any commits that conflict with another Iceberg operation will be ignored. This mode will create additional snapshots in the table history, one for each commit.
因為在獲取文件的時候,此時只能讀取到a和b下的數據文件,a和b下沒有delete文件,所以沒有讀取a和b下數據文件的min和max。 在做merge的時候,最新的snapshot是d,此時有delete文件,所以需要判斷該delete文件是否能夠匹配上前面讀取的數據文件。匹配條件有兩個,一個是sequenceNumber,一個是最大最小值是否有交集。delete的文件是后生成的,它的sequenceNumber肯定是大於前面a,b下的數據文件,所以該條件滿足。因為在讀取a,b下的數據文件的時候,沒有讀取min,max,導致不能夠跟delete文件做值的交叉范圍判斷,所以data文件中被關聯了delete文件,所以這種情況下,雖然只對 a和b做合並,且后續修改的數據文件沒有被修改,但依然會合並失敗。
如果在讀取a,b下數據文件的時候,把對應的min,max也讀取上來,那么就可以合並成功,對應流程在 ManifestGroup.planFiles中,讀取內容由 columns 決定。
- 成功:生成最新快照e,最終的快照為:a,b,c,d,e
- 成功,但沒生成新的快照:參考上面說明
結論:雖然后續修改的數據並不在合並的數據中,但USE_STARTING_SEQUENCE_NUMBER為false依然會失敗,具體原因已在上面說明。
結論
1、PARTIAL_PROGRESS_ENABLED
當該參數為true時,雖然它最終能讓任務執行完成,但實際上它忽略子提交失敗的情況,所以實際有沒有做合並與該參數無關。
2、USE_STARTING_SEQUENCE_NUMBER
設置該參數為true,可以修改新生成的dataFile和manifest的sequenceNumber為原來的number,這樣在讀取數據的時候,就可以把delteFile應用到新生成的dataFile中了,可以解決大多數數據沖突的情況。