Nhóm của tôi đang xây dựng quy trình ETL để tải các tệp văn bản được phân tách thô thành một "Hồ dữ liệu" dựa trên Ván sàn sử dụng Spark. Một trong những lời hứa của cửa hàng cột Parquet là một truy vấn sẽ chỉ đọc các "cột sọc" cần thiết.Tại sao Apache Spark đọc các cột Parquet không cần thiết trong các cấu trúc lồng nhau?
Nhưng chúng tôi thấy các cột không mong muốn được đọc cho cấu trúc giản đồ lồng nhau.
Để chứng minh, đây là một POC sử dụng Scala và vỏ Spark 2.0.1:
// Preliminary setup
sc.setLogLevel("INFO")
import org.apache.spark.sql.types._
import org.apache.spark.sql._
// Create a schema with nested complex structures
val schema = StructType(Seq(
StructField("F1", IntegerType),
StructField("F2", IntegerType),
StructField("Orig", StructType(Seq(
StructField("F1", StringType),
StructField("F2", StringType))))))
// Create some sample data
val data = spark.createDataFrame(
sc.parallelize(Seq(
Row(1, 2, Row("1", "2")),
Row(3, null, Row("3", "ABC")))),
schema)
// Save it
data.write.mode(SaveMode.Overwrite).parquet("data.parquet")
Sau đó, chúng ta đọc các tập tin trở lại vào một DataFrame và dự án cho một tập hợp các cột:
// Read it back into another DataFrame
val df = spark.read.parquet("data.parquet")
// Select & show a subset of the columns
df.select($"F1", $"Orig.F1").show
Khi điều này chạy chúng ta thấy sản lượng dự kiến:
+---+-------+
| F1|Orig_F1|
+---+-------+
| 1| 1|
| 3| 3|
+---+-------+
... Nhưng kế hoạch truy vấn cho thấy một hơi differen t câu chuyện:
"Kế hoạch tối ưu hóa" cho thấy:
val projected = df.select($"F1", $"Orig.F1".as("Orig_F1"))
projected.queryExecution.optimizedPlan
// Project [F1#18, Orig#20.F1 AS Orig_F1#116]
// +- Relation[F1#18,F2#19,Orig#20] parquet
Và "giải thích" show:
projected.explain
// == Physical Plan ==
// *Project [F1#18, Orig#20.F1 AS Orig_F1#116]
// +- *Scan parquet [F1#18,Orig#20] Format: ParquetFormat, InputPaths: hdfs://sandbox.hortonworks.com:8020/user/stephenp/data.parquet, PartitionFilters: [], PushedFilters: [], ReadSchema: struct<F1:int,Orig:struct<F1:string,F2:string>>
Và các bản ghi INFO ra trong quá trình thực hiện cũng xác nhận rằng các cột Orig.F2 là bất ngờ đọc:
16/10/21 15:13:15 INFO parquet.ParquetReadSupport: Going to read the following fields from the Parquet file:
Parquet form:
message spark_schema {
optional int32 F1;
optional group Orig {
optional binary F1 (UTF8);
optional binary F2 (UTF8);
}
}
Catalyst form:
StructType(StructField(F1,IntegerType,true), StructField(Orig,StructType(StructField(F1,StringType,true), StructField(F2,StringType,true)),true))
Theo số Dremel paper và Parquet documentation, cột cho cấu trúc lồng nhau phức tạp nên được lưu trữ độc lập và có thể khôi phục độc lập.
Câu hỏi:
- là hành vi này một hạn chế của các công cụ truy vấn Spark hiện tại? Nói cách khác, liệu Parquet có hỗ trợ tối ưu thực hiện truy vấn này, nhưng kế hoạch truy vấn của Spark là ngây thơ?
- Hoặc, đây có phải là hạn chế của việc triển khai Parquet hiện tại không?
- Hoặc, tôi có đang sử dụng API Spark chính xác không?
- Hoặc, tôi có hiểu lầm về cách lưu trữ cột Dremel/Parquet được cho là hoạt động không?
Có thể liên quan: Why does the query performance differ with nested columns in Spark SQL?
Đây là vấn đề về công cụ truy vấn Spark. –
@LostInOverflow, bạn có biết điều này có trong trình theo dõi vấn đề Spark không? https://issues.apache.org/jira/browse/SPARK/?selectedTab=com.atlassian.jira.jira-projects-plugin:issues-panel –
Dường như Parquet nên hỗ trợ kịch bản này theo @ julien-le- dem https://twitter.com/J_/status/789584704169123841 –