Spark DataFrame读写

时间:2018-11-18 11:02:50

标签: scala apache-spark hive

我有一个用例,其中我必须将数百万个json格式的数据加载到Apache Hive表中。 所以我的解决方案很简单,将它们加载到数据帧中并将它们编写为Parquet文件。 然后,我将在它们上创建一个外部表。

我正在使用带有Scala 2.11.8的Apache Spark 2.1.0。

所有的消息都遵循一种灵活的模式。 例如,列“金额”可以具有-1.0或1的值。

由于我正在将数据从半结构化格式转换为结构化格式,但是我的架构略有不同 变量,我认为inferSchema选项可以补偿json之类的数据源,从而对我有所帮助。

spark.read.option("inferSchema","true").json(RDD[String])

当我在读取json数据时将inferSchema用作true时,

情况1:对于较小的数据,所有镶木地板文件的数量均为两倍。

情况2:对于较大的数据,某些实木复合地板文件的数量是其两倍,而其他实木复合地板的文件是int64。

我尝试调试并发现某些概念,例如模式演变和模式合并 让我头晕目眩,给我留下的疑问多于答案。

我的疑问/问题是

  1. 当我尝试推断架构时,它不会将推断的架构强制实施到完整数据集吗?

  2. 由于我的矛盾,我无法强制执行任何模式,因此我考虑将全部内容强制转换 将数据类型加倍的列,因为它可以同时具有整数和十进制数。 有没有更简单的方法?

  3. 我的猜测是,由于数据已分区,因此inferSchema按分区工作,然后 它给了我一个通用的模式,但是它不像执行模式那样执行任何操作 这样的。如果我错了,请纠正我。

注意:我使用inferSchema选项的原因是因为传入的数据过于灵活/多变        尽管有些列是强制性的,但是可以强制执行我自己的案例类。如果您有更简单的解决方案,请提出建议。

1 个答案:

答案 0 :(得分:0)

推理模式实际上只是处理所有行以查找类型。 完成后,它将合并结果以找到整个数据集共有的模式。

例如,您的某些字段可能在某些行中具有值,但在其他行中则没有。因此,此字段的推断模式将变为可空。

要回答您的问题,可以推断输入模式。 但是,由于打算在Hive中使用输出,因此应确保所有输出文件都具有相同的架构。

一个简单的方法是使用铸造(如您所建议)。我通常喜欢在工作的最后阶段进行选择,只列出所有列和类型。我觉得这使这项工作更具可读性。

例如

df
.coalesce(numOutputFiles)
.select(
  $"col1"        .cast(IntegerType).as("col1"),
  $"col2"        .cast( StringType).as("col2"),
  $"someOtherCol".cast(IntegerType).as("col3")
)
.write.parquet(outPath)