本文旨在介绍 Spark 读取tinyInt字段时,如何处理精度损失的情况
MySQLDialect
spark中,mysql的方言主要约定了数据库中varbinary、bit和tinyint类型的特殊映射,其他类型使用默认映射,源码如下:
private case object MySQLDialect extends JdbcDialect {
override def getCatalystType(
sqlType: Int, typeName: String, size: Int, md: MetadataBuilder): Option[DataType] = {
if (sqlType == Types.VARBINARY && typeName.equals("BIT") && size != 1) {
md.putLong("binarylong", 1)
Option(LongType)
} else if (sqlType == Types.BIT && typeName.equals("TINYINT")) {
Option(BooleanType)
} else None
}
....
}
从源码中可以看出,当spark取出表的scheme中,类型名为tinyint
的字段,会被处理为Boolean
型。而mysql中tinyint的sqlType都会默认处理为bit,所以如果数据库中的这类字段中,存储了0、1之外的值,拉取数据时则会出现数据失真。
处理方式:
在JDBC的URL中加入参数:tinyInt1isBit=false
spark JDBC的源码分析,可以参考文档:Spark JDBC系列–源码简析