查询时,大量的大十进制类型为null

时间:2019-02-28 13:24:04

标签: apache-spark

我有一个简单的火花代码,如下所示,我想查询大量的大十进制类型

 test("SparkTest 0458") {
    val spark = SparkSession.builder().master("local").appName("SparkTest0456").getOrCreate()
    import spark.implicits._
    val data =
    (
      new java.math.BigDecimal("819021675302547012738064321"),
      new java.math.BigDecimal("819021675302547012738064321"),
      new java.math.BigDecimal("819021675302547012738064321")
    )

    val df = spark.createDataset(Seq(data)).toDF("a", "b", "c")
    df.show(truncate = false)
  }

但是它显示3个空值

+----+----+----+
|a   |b   |c   |
+----+----+----+
|null|null|null|
+----+----+----+

我会问这是怎么回事,谢谢

1 个答案:

答案 0 :(得分:1)

问题的根源是十进制类型的模式推断机制。由于小数位数和精度都不是类型签名的一部分,因此Spark假定输入为decimal(38, 18)

df.printSchema
root
 |-- a: decimal(38,18) (nullable = true)
 |-- b: decimal(38,18) (nullable = true)
 |-- c: decimal(38,18) (nullable = true)

这意味着您最多可以在小数点前存储20位数字,并且您使用的数字有26位数字。

据我所知,尚无直接与反射配合使用的解决方法,但可以将数据转换为Row对象并显式提供架构。例如使用中间RDD

import org.apache.spark.sql.types._
import org.apache.spark.sql.Row
import java.math.BigDecimal

val schema = StructType(
  Seq("a", "b", "c") map (c => StructField(c, DecimalType(38, 0)))
)

spark.createDataFrame(
  sc.parallelize(Seq(data)) map(t => Row(t.productIterator.toSeq: _*)),
  schema
)

或Kryo序列化数据集

import org.apache.spark.sql.{Encoder, Encoders}
import org.apache.spark.sql.catalyst.encoders.RowEncoder

spark.createDataset(Seq(data))(
  Encoders.kryo: Encoder[(BigDecimal, BigDecimal, BigDecimal)]
).map(t => Row(t.productIterator.toSeq: _*))(RowEncoder(schema))