Фрейм данных Spark (v 2.3.2) считывает все столбцы в файле ORC как строковый тип. это нормальное поведение? - PullRequest
0 голосов
/ 16 октября 2019

У меня есть куча CSV-файлов, которые загружаются в HDFS в формате ORC с использованием инструмента ETL Informatica. После загрузки в HDFS я хотел извлечь метаданные (имена столбцов, типы данных) файлов ORC.

Но когда я загружал файлы ORC в кадры данных Spark, все столбцы оцениваются как string type.

Пример данных:

ID|Course|Enrol_Date|Credits
123|Biology|21-03-2012 07:34:56|24
908|Linguistics|05-02-2012 11:02:36|15
564|Computer Science|18-03-2012 09:48:09|30
341|Philosophy|23-01-2012 18:12:44|10
487|Math|10-04-2012 17:00:46|20

Для этого я использую следующие команды:

df = sqlContext.sql("SELECT * FROM orc.`<HDFS_path>`");
df.printSchema()

Пример вывода:

root
 |-- ID: string (nullable = true)
 |-- Course: string (nullable = true)
 |-- Enrol_Date: string (nullable = true)
 |-- Credits: string (nullable = true)

Я совершенно новичок в Spark и HDFS. Я пытаюсь понять, почему каждый столбец приводит к типу string. Это нормальное поведение при создании ORC с исходными файлами CSV (независимо от того, какой инструмент мы используем для этого)? Или я не правильно что-то делаю в искре, которая вызывает это?

Ответы [ 2 ]

0 голосов
/ 16 октября 2019

По умолчанию, спарк читает все поля как StringType . Вы можете попробовать ниже:

Для логической схемы,

val data = spark.read.format("csv").option("header", "true").option("inferSchema", "true").load("<path>.csv")

Для предоставления пользовательской схемы

import org.apache.spark.sql.types._

val customSchema = StructType(Array(
  StructField("col1", StringType, true),
  StructField("col2", IntegerType, true),
  StructField("col3", DoubleType, true))
)

val data = spark.read.format("csv").option("header", "true").schema(customSchema).load("<path>.csv")
0 голосов
/ 16 октября 2019

Вы должны cast или использовать schema при импорте CSV файла через Informatica . Поскольку формат Spark ORC не infer Schema автоматически, как формат Spark CSV. Формат ORC берет схему из схемы исходного файла как есть.

Поскольку вы не использовали schema в Informatica , в нем по умолчанию записаны данные String DataType, который далее используетсяна ORC.

Существует два возможных способа решения проблемы:

  1. Либо используйте схему в файле CSV (преобразуйте столбцы, которые должны иметь тип данных, отличный от String) в Informatica / Spark и загрузите в ORC.

  2. Или используйте Struct или Casting в Spark, чтобы изменить тип данных файла ORC для необходимых столбцов.

Пример демонстрации:

Ниже приведен пример демонстрации работы искры с Schema. Вы можете напоминать логику схемы исходного CSV файла в Informatica, как и Spark, как показано ниже

Случай 1: загрузка файла CSV по умолчанию и запись в ORC

scala> val df = spark.read.format("csv").option("header","true").load("/spath/stack2.csv")

//Default schema uses by Spark or Informatica for CSV file

scala> df.printSchema
root
 |-- ID: string (nullable = true)
 |-- Course: string (nullable = true)
 |-- Enrol_Date: string (nullable = true)
 |-- Credits: string (nullable = true)

//Have loaded same CSV file into ORC

scala> df.write.format("orc").mode("overwrite").save("/spath/AP_ORC")

scala> val orc = spark.read.format("orc").load("/spath/AP_ORC")

//Schema is same as Source CSV file

scala> orc.printSchema
root
 |-- ID: string (nullable = true)
 |-- Course: string (nullable = true)
 |-- Enrol_Date: string (nullable = true)
 |-- Credits: string (nullable = true)

Случай 2: Преобразование / вывод типа данных схемы для файла CSV и запись в ORC

//Inferring Schema or Transform/casting of CSV data in Spark or Informatica respectively. 

scala> val df = spark.read.format("csv").option("header","true").option("inferschema", "true").load("/spath/stack2.csv")

//Transformed Schema
scala> df.printSchema
root
 |-- ID: integer (nullable = true)
 |-- Course: string (nullable = true)
 |-- Enrol_Date: string (nullable = true)
 |-- Credits: integer (nullable = true)

//Have loaded same CSV file into ORC

scala> df.write.format("orc").mode("overwrite").save("/spath/AP_ORC")

scala> val orc = spark.read.format("orc").load("/spath/AP_ORC")

 //Schema is same as Source CSV file

scala> orc.printSchema
root
 |-- ID: integer (nullable = true)
 |-- Course: string (nullable = true)
 |-- Enrol_Date: string (nullable = true)
 |-- Credits: integer (nullable = true)
...