apache-spark - read - spark temp view



Почему Apache Spark считывает ненужные столбцы Parquet во вложенных структурах? (1)

Моя команда строит процесс ETL для загрузки необработанных текстовых файлов с разделителями в «озеро данных» на основе Parquet с использованием Spark. Одно из обещаний хранилища столбцов Parquet заключается в том, что запрос будет считывать только необходимые «полосы столбцов».

Но мы видим, как неожиданные столбцы читаются для вложенных структур схемы.

Для демонстрации приведем POC с использованием Scala и оболочки 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")

Затем мы читаем файл обратно в DataFrame и проецируем в подмножество столбцов:

// 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

Когда это выполняется, мы видим ожидаемый результат:

+---+-------+
| F1|Orig_F1|
+---+-------+
|  1|      1|
|  3|      3|
+---+-------+

Но ... план запроса показывает немного другую историю:

«Оптимизированный план» показывает:

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

И "объяснить" показывает:

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>>

И журналы INFO, созданные во время выполнения, также подтверждают, что столбец Orig.F2 неожиданно прочитан:

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))

Согласно документу Dremel и документации Parquet , столбцы для сложных вложенных структур должны храниться независимо и извлекаться независимо.

Вопросы:

  1. Является ли это поведение ограничением текущего механизма запросов Spark? Другими словами, поддерживает ли Parquet оптимальное выполнение этого запроса, но планировщик запросов Spark наивен?
  2. Или это ограничение текущей реализации Parquet?
  3. Или я не правильно использую API Spark?
  4. Или я неправильно понимаю, как должно работать хранилище колонок Dremel / Parquet?

Возможно связано: Почему производительность запросов отличается от вложенных столбцов в Spark SQL?


На данный момент это ограничение для механизма запросов Spark, соответствующий билет JIRA приведен ниже, спарк обрабатывает только предикатное нажатие простых типов в Parquet, а не вложенных StructTypes

https://issues.apache.org/jira/browse/SPARK-17636





parquet