Spark & Hive 关于parquet格式文件的区别

      因为数据之前一直都在MySQL库中保存,现在需要将部分数据移到hive库中,由于数据在MySQL是分库分表存储的,试了很多方式直接从MySQL到Hive库中都没有成功,于是,采用spark读取MySQL数据输出到parquet文件中,再load到Hive中,这才遇到了这个问题。
      将spark输出的parquet文件按分区load到hive中,出现load到hive中的字段比MySQL库中的原有字段少,并且是数值为null的字段.

load  data local inpath ‘/home/user/test/parquent/’ into  table  test   partition(dt='2019080')

于是就开始了苦逼的排查之路,首先是从MySQL读取数据转成DataSet时候是否有问题,DataSet.show出来是正常的

接下来测试,如果输出json文件时字段是否正常,显示发现数值为null的字段不见了(^_^···············)

{
"accountid": "ae724dda15",
"amount": "149",
"createtime": "2019-08-08 11:07:10.0",
"createuser": "admin",
"delStatus": "0",
"discountsdetail": "http://ef7536df-3703-40c3-9564-151bbda0f9a0.html",
"discountsname": "省5分",
"dt": "20190808",
"id": "34545b6de3540e",
"paytypecode": "002",
"paytypename": "营销活动",
"saleno": "151505SM5556502",
"sorts": "0",
"tenantid": "c58471455680",
"updatetime": "2019-08-08 11:07:10.0",
"updateuser": "admin"
}

想了一下总感觉不合理,于是继续测试,使用spark去读取该json/parquet文件,发现该数据的schema和数据和MySQL是一样的,并且数据也是正常的

Spark & Hive 关于parquet格式文件的区别_第1张图片

测试完以后还不清楚哪里出了问题,就开始debug和度娘,发现spark在save()时使用的是spark自带的序列化/反序列化方法,为了较好的性能会使用自己默认的parquet格式而不是采用hive SerDe,该行为是通过参 spark.sql.hive.convertMetastoreParquet空值,默认是true。

spark.sql.hive.convertMetastoreParquet default is true.When set to false, Spark
SQL will use the Hive SerDe for parquet tables instead of the built in support.

当向Hive metastore中读写Parquet表时,Spark SQL将使用Spark SQL自带的Parquet SerDe(SerDe:Serialize/Deserilize的简称,目的是用于序列化和反序列化),而不是用Hive的SerDe,Spark SQL自带的SerDe拥有更好的性能。这个优化的配置参数为spark.sql.hive.convertMetastoreParquet,默认值为开启。

 

Parquet 数据源支持自动检测新作列并且会合并schema。由于合并schema是一个相当耗费性能的操作,而且很多情况下都是不必要的,所以从spark 1.5开始就默认关闭掉该功能。有两种配置开启方式:全局sql配置中设置spark.sql.parquet.mergeSchema 为true. 、通过数据源option设置mergeSchema为true。

其他parquet相关参数可以通过setconf & .config()设置

spark.sql.parquet.binaryAsString 默认值是false。一些parquet生产系统,尤其是impala,hive和老版本的spark sql,不区分binary和string类型。该参数告诉spark 讲binary数据当作字符串处理。

spark.sql.parquet.int96AsTimestamp 默认是true。有些parquet生产系统,尤其是parquet和hive,将timestamp翻译成INT96.该参数会提示Spark SQL讲INT96翻译成timestamp。

spark.sql.parquet.compression.codec 默认是snappy。当写parquet文件的时候设置压缩格式。如果在option或者properties里配置了compression或者parquet.compression优先级依次是:compression,parquet.compression,spark.sql.parquet.compression.codec。支持的配置类型有:none,uncompressed,snappy,gzip,lzo,brotli,lz4,zstd。在hadoop2.9.0之前,zstd需要安装ZstandardCodec,brotli需要安装BrotliCodec。

spark.sql.parquet.filterPushdown 默认是true。设置为true代表开启parquet下推执行优化。

spark.sql.hive.convertMetastoreParquet 默认是true。假如设置为false,spark sql会读取hive parquet表的时候使用Hive SerDe,替代内置的。

spark.sql.parquet.mergeSchema 默认是false。当设置为true的时候,parquet数据源会合并读取所有的parquet文件的schema,否则会从summary文件或者假如没有summary文件的话随机的选一些数据文件来合并schema。

spark.sql.parquet.writeLegacyFormat 默认是false。如果设置为true 数据会以spark 1.4和更早的版本的格式写入。比如,decimal类型的值会被以apache parquet的fixed-length byte array格式写出,该格式是其他系统例如hive,impala等使用的。如果是false,会使用parquet的新版格式。例如,decimals会以int-based格式写出。如果spark sql要以parquet输出并且结果会被不支持新格式的其他系统使用的话,需要设置为true。

遇到问题记录一下 …………

                                               ^.^  ^.^  ^.^

你可能感兴趣的:(spark)