SparkSQL读取MySQL数据tinyint字段转换成boolean类型的解决方案

最近在做弄sparksql,在读取mysql数据的时候发现一个问题, 在数据库将字段定义成tinyint,并且长度为1的时候,读取到spark里面,被转换成Boolean类型的字段了.
测试表定义

CREATE TABLE `test1` (
  `id` bigint(4) NOT NULL AUTO_INCREMENT,
  `name` varchar(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `score` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


SparkSQL读取MySQL数据tinyint字段转换成boolean类型的解决方案_第1张图片
在网上查找了以后,发现是spark对mysql方言的约束,约定了数据库中varbinary、bit和tinyint类型的特殊映射,其他类型使用默认映射.
这里的源码在MySQLDialect中,贴一下源码

override def getCatalystType(
      sqlType: Int, typeName: String, size: Int, md: MetadataBuilder): Option[DataType] = {
    if (sqlType == Types.VARBINARY && typeName.equals("BIT") && size != 1) {
      // This could instead be a BinaryType if we'd rather return bit-vectors of up to 64 bits as
      // byte arrays instead of longs.
      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
例:jdbc:mysql://localhost:3307/test?tinyInt1isBit=false
参考:Spark JDBC系列–Mysql tinyInt字段特殊处理

你可能感兴趣的:(大数据,spark)