Spark 大/小文件讀取優化

問題描述

使用Spark寫複雜SQL時,我們經常會遇到兩個尷尬的情況:

  • 表裏的單個文件都很大,而且因爲record比較小,所以單個文件的record數量巨大。

  • 表裏每個分區都有成百上千個小文件,單個文件可能只有幾條記錄

對於第一種情況,會導致我們沒辦法充分利用我們已有的核,所以速度很慢。

對於第二種情況,則會大量浪費調度時間。比如你有100萬個文件,假設只有100個核,那麼需要調度一萬輪,每輪調度除了調度自身的消耗,還有很多額外的消耗。在沒有shuffle的情況下,會導致寫太多文件,本身就浪費性能,如果有shuffle,則對這麼多map進行合併,本身也帶來額外消耗。所以最佳辦法是在讀取的時候就能生成較少的分區,從而減少開銷。

大文件優化讀取優化

大文件優化讀取需要關注兩個參數:

spark.files.maxPartitionBytes=   默認128m
parquet.block.size= 默認128m

第一個參數是針對session有效的,也就是因爲這你在讀的時候設置就會立刻生效。在沒有第二個參數配合的情況下,就已經能夠增加分區數了,缺點是,分區裏的數據可能不會很均勻,因爲均勻程度也會受到第二個參數的影響。

然而,第二個參數需要寫入的時候就配置上。所以大家有條件可以設置下,方便遇到文件較大,然後單條記錄又很小的情況下,查詢可以更靈活控制。

小文件讀取優化

小文件讀取首先有基礎參數要設置(其中parquet已經是默認打開的),分別是針對parquet格式和ORC的。

spark.sql.hive.convertMetastoreParquet=true (默認已經爲true)
spark.sql.hive.convertMetastoreOrc=true

只要是 Parquet 或者 ORC,無論是 Hive 表還是 datasource,默認都走 FileScan,都支持合併。所以大部分情況,這兩個參數大家可以當做不存在。

接下來就是通過另外兩個參數來控制怎麼進行小文件合併了(多個文件合併成一個分區):

spark.files.maxPartitionBytes=   默認128m
spark.files.openCostInBytes=     默認4m

我們簡單解釋下這兩個參數(注意他們的單位都是bytes):

  •  maxPartitionBytes參數控制一個分區最大多少。

  •  openCostInBytes控制當一個文件小於該閾值時,會繼續掃描新的文件將其放到到一個分區

所以理論上你可以將openCostInBytes再設置大一點,減少分區讀取。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章