簡體   English   中英

如何在hdfs中設置文件的行組大小?

[英]How do you set the row group size of files in hdfs?

我正在對hdfs中的塊大小(dfs.block.size)和行組大小(parquet.block.size)進行一些實驗。

我在hdfs中有大量數據,我想復制具有各種塊大小和行組大小的數據以進行測試。 我可以使用以下方法以不同的塊大小復制數據:

hdfs dfs -D dfs.block.size=67108864 -D parquet.block.size=67108864 -cp /new_sample_parquet /new_sample_parquet_64M

但是只有dfs.block.size被更改。 我正在使用hdfs dfs -stat驗證塊大小,並使用parquet-tools meta行組大小。 實際上,如果我用blah.blah.blah替換parquet.block.size ,則效果相同。 我什至進入spark-shell並使用以下命令手動設置parquet.block.size屬性

sc.hadoopConfiguration.setInt("parquet.block.size", 67108864).

我正在使用hadoop 3.1.0。 我從這里獲得了parquet.block.size的屬性名稱。

這是我嘗試輸出的前10行

row group 1:                    RC:4140100 TS:150147503 OFFSET:4
row group 2:                    RC:3520100 TS:158294646 OFFSET:59176084
row group 3:                    RC:880100 TS:80122359 OFFSET:119985867
row group 4:                    RC:583579 TS:197303521 OFFSET:149394540
row group 5:                    RC:585594 TS:194850776 OFFSET:213638039
row group 6:                    RC:2620100 TS:130170698 OFFSET:277223867
row group 7:                    RC:2750100 TS:136761819 OFFSET:332088066
row group 8:                    RC:1790100 TS:86766854 OFFSET:389772650
row group 9:                    RC:2620100 TS:125876377 OFFSET:428147454
row group 10:                   RC:1700100 TS:83791047 OFFSET:483600973

如您所知,TS(總大小)遠大於64MB(67108864字節)

我目前的理論:

我這樣做是在spark-shell中:

sc.hadoopConfiguration.setInt("parquet.block.size", 67108864)
val a = spark.read.parquet("my_sample_data")
a.rdd.getNumPartitions // 1034
val s = a.coalesce(27)
s.write.format("parquet").mode("Overwrite").options(Map("dfs.block.size" -> "67108864")).save("/my_new_sample_data")

也許是因為我的輸入數據已經有1034個分區。 我真的不確定。 我的數據每行大約有118列。

parquet.block.size屬性僅影響Parquet編寫器。 另一方面, hdfs dfs -cp命令將復制文件而不管其內容如何。 因此, hdfs dfs -cp將忽略parquet.block.size屬性。

假設您有一個應用程序以JPG或PNG格式截屏,具體取決於配置文件。 您可以使用cp命令復制這些屏幕截圖。 自然地,即使您在配置文件中更改了所需的圖像格式, cp命令也將始終以原始文件的圖像格式創建輸出文件,而不管配置文件如何。 配置文件僅由屏幕截圖應用程序使用,而cp則不使用。 這也是parquet.block.size屬性的工作方式。

可以更改塊大小的方法是重寫文件。 你提到你有spark-shell 通過發出該命令來重寫Parquet文件

sc.hadoopConfiguration.setInt("parquet.block.size", 67108864)
var df = spark.read.parquet("/path/to/input.parquet")
df.write.parquet("/path/to/output")

更新 :由於您在下面的評論中提到它不適用於您,因此我進行了實驗並在下面發布了會話記錄:

$ spark-shell
scala> sc.hadoopConfiguration.setInt("parquet.block.size", 200000)
scala> var df = spark.read.parquet("/tmp/infile.parquet")
df: org.apache.spark.sql.DataFrame = [field0000: binary, field0001: binary ... 78 more fields]
scala> df.write.parquet("/tmp/200K")
scala> df.write.format("parquet").mode("Overwrite").options(Map("parquet.block.size" -> "300000")).save("/tmp/300K")
scala> :quit
$ hadoop fs -copyToLocal /tmp/{200K,300K} /tmp
$ parquet-tools meta /tmp/infile.parquet | grep "row group" | head -n 3
row group 1:  RC:4291 TS:5004800 OFFSET:4
row group 2:  RC:3854 TS:4499360 OFFSET:5004804
row group 3:  RC:4293 TS:5004640 OFFSET:10000000
$ parquet-tools meta /tmp/200K/part-00000-* | grep "row group" | head -n 3
row group 1:   RC:169 TS:202080 OFFSET:4
row group 2:   RC:168 TS:201760 OFFSET:190164
row group 3:   RC:169 TS:203680 OFFSET:380324
$ parquet-tools meta /tmp/300K/part-00000-* | grep "row group" | head -n 3
row group 1:   RC:254 TS:302720 OFFSET:4
row group 2:   RC:255 TS:303280 OFFSET:284004
row group 3:   RC:263 TS:303200 OFFSET:568884

通過查看TS值,您可以看到輸入文件的行組大小為4.5-5M,輸出文件的行組大小分別為200K和300K。 這表明使用sc.hadoopConfiguration設置的值成為“默認值”,而您在下面的注釋中提到的涉及df.options的其他方法將覆蓋此默認值。

更新2 :現在您已經發布了輸出,我可以看到發生了什么。 在您的情況下,正在進行壓縮,從而增加了適合行組的數據量。 行組大小適用於壓縮數據,但TS顯示未壓縮數據的大小。 但是,您可以通過減去行的起始偏移量來推斷行組的大小。 例如,第一行組的壓縮大小為59176084-4 = 59176080字節或更小(因為也可以進行填充)。 我將您的結果復制到計算機上的/tmp/rowgroups.dat中,並通過發出以下命令來計算行組大小:

$ cat /tmp/rowgroups.dat | sed 's/.*OFFSET://' | numinterval
59176080
60809783
29408673
64243499
63585828
54864199
57684584
38374804
55453519

numinterval命令在Ubuntu上的num-utils軟件包中。)如您所見,所有行組都小於您指定的行組大小。 (之所以不完全指定大小,是因為PARQUET-1337 。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM