Apache spark Spark(v2.3.2)dataframe正在以字符串类型读取ORC文件中的所有列。这是正常的行为吗?

Apache spark Spark(v2.3.2)dataframe正在以字符串类型读取ORC文件中的所有列。这是正常的行为吗?,apache-spark,orc,Apache Spark,Orc,我有一堆CSV文件,正在使用ETL工具Informatica以ORC格式加载到HDFS中。加载到HDFS后,我想提取ORC文件的元数据(列名、数据类型) 但是当我将ORC文件加载到Spark数据帧中时,所有列都被赋值为stringtype 样本数据: 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|

我有一堆CSV文件,正在使用ETL工具Informatica以ORC格式加载到HDFS中。加载到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()

我对Spark和HDFS完全是新手。我试图理解为什么每一列都是
string
类型的结果。这是否是使用csv源文件创建ORC时的正常行为(无论我们使用哪种工具)?还是我在spark中没有正确执行导致此问题的操作?

在通过Informatica导入
CSV
文件时,您应该
cast
或使用
schema
。由于Spark
ORC
格式不会像Spark
CSV
格式那样自动推断模式。ORC格式按原样从源文件架构获取架构

由于您没有在Informatica中使用任何
模式
,因此它以默认的
字符串
数据类型写入数据,而
ORC
将进一步采用该数据类型

有两种可能的解决方法:

  • 或者在CSV文件中使用架构(应具有 在
    Informatica
    /
    Spark
    中加载到
    ORC
    中的
    String
    以外的数据类型

  • 或者在Spark中使用
    Struct
    Casting
    更改所需列的
    ORC
    文件的数据类型

  • 示例演示:

    下面是spark如何使用
    Schema
    的示例演示。您可以将
    Informatica
    中源
    CSV
    文件的模式逻辑与
    Spark
    中的逻辑相似,如下所示

    案例1:默认加载CSV文件并写入ORC

    案例2:转换/推断CSV文件的模式数据类型并写入ORC


    默认情况下,spark将所有字段读取为StringType。您可以在下面尝试:

    为了推断模式

    val data = spark.read.format("csv").option("header", "true").option("inferSchema", "true").load("<path>.csv")
    
    val data=spark.read.format(“csv”).option(“header”、“true”).option(“inferSchema”、“true”).load(“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")
    
    import org.apache.spark.sql.types_
    val customSchema=StructType(数组(
    StructField(“col1”,StringType,true),
    StructField(“col2”,IntegerType,true),
    StructField(“col3”,双类型,true))
    )
    val data=spark.read.format(“csv”).选项(“标头”、“true”).架构(customSchema).load(.csv”)
    
    我刚刚尝试了这个方法,但它仍然将所有列都设置为
    string
    type。这种情况可能有什么原因吗?你能检查一下你是如何通过Informatica加载数据的吗?你是否使用了任何模式?你能提供你的样本数据吗?编辑了这个问题,添加了样本数据及其输出。不,我没有在Informatica中使用任何模式。这是一个动态映射,使用参数选择每个文件。感谢您的输入。但是在我的例子中,提供一个自定义模式并不是一种有效的方法,因为我有很多列的文件。因此,我的目标是自动提取数据类型信息,而不是手动提供。我需要这些信息来在配置单元中创建外部表。实际上,即使有100个列,提供自定义模式也是有效的方法。因为,在推断模式时,spark会遍历每个数据点&推断,有效地读取整个数据。但是,当您提供模式时,实际上您节省了推断ok的时间。我不知道。谢谢你的澄清。我所说的低效是指我必须为这100列中的每一列手动键入数据类型。但是你所说的在减少spark的负载方面也是有意义的。在相关情况下,我会记住这一点。但现在,我不知道一个文件可能有多少列或它们的数据类型。我现在唯一的目的是使用这些信息在Hive中形成
    createexternaltable
    语句
    //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)
    
    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")