設(shè)置為false時,會使用parquet的新版格式。例如,decimals會以int-based格式寫出。如果Spark SQL要以Parquet輸出并且結(jié)果會被不支持新格式的其他系統(tǒng)使用的話,需要設(shè)置為true。
比如,對于decimal數(shù)據(jù)類型的兼容處理,不設(shè)置true時,經(jīng)常會報類似如下的錯誤:

Job aborted due to stage failure: Task 0 in stage 0.0 failed 1 times, most recent failure: Lost task 0.0 in stage 0.0 (TID 0, localhost, executor driver): parquet.io.ParquetDecodingException: Can not read value at 0 in block -1 in file hdfs://hadoop/data/test_decimal/dt=20200515000000/part-00000-9820eba2-8a40-446d-8c28-37027a1b1f2d-c000.snappy.parquet at parquet.hadoop.InternalParquetRecordReader.nextKeyValue(InternalParquetRecordReader.java:228)
  at parquet.hadoop.ParquetRecordReader.nextKeyValue(ParquetRecordReader.java:201)
  at org.apache.hadoop.hive.ql.io.parquet.read.ParquetRecordReaderWrapper.<init>(ParquetRecordReaderWrapper.java:122)
  at org.apache.hadoop.hive.ql.io.parquet.read.ParquetRecordReaderWrapper.<init>(ParquetRecordReaderWrapper.java:85)
  at org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat.getRecordReader(MapredParquetInputFormat.java:72)
Caused by: java.lang.UnsupportedOperationException: parquet.column.values.dictionary.PlainValuesDictionary$PlainLongDictionary at parquet.column.Dictionary.decodeToBinary(Dictionary.java:44)

此時我們需要將spark.sql.parquet.writeLegacyFormat設(shè)置為true來解決上述的異常問題。

但如果同時設(shè)置spark.sql.hive.convertMetastoreParquet為false時,要注意一些數(shù)據(jù)類型以及精度的處理,比如對于decimal類型的處理。通過一個例子復(fù)原一下當時的場景:

1.創(chuàng)建Hive外部表testdb.test_decimal,其中字段fee_rate為decimal(10,10)

CREATE EXTERNAL TABLE `testdb`.`test_decimal`(`no` STRING , `fee_rate` DECIMAL(10,10)) 
PARTITIONED BY (`dt` STRING ) ROW FORMAT SERDE \\\'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe\\\' WITH SERDEPROPERTIES ( \\\'serialization.format\\\' = \\\'1\\\' ) STORED AS INPUTFORMAT \\\'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat\\\' OUTPUTFORMAT \\\'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat\\\' LOCATION \\\'hdfs://hadoop/data/test_decimal\\\' TBLPROPERTIES ( \\\'transient_lastDdlTime\\\' = \\\'1589160440\\\' ) ;

2.將testdb.item中的數(shù)據(jù)處理后保存到testdb.test_decimal中

// 這里為了展示方便,直接查詢testdb.item中的數(shù)據(jù)
// 注意: 字段fee_rate的類型為decimal(10,6)
select no, fee_rate from testdb.item  where dt=20190528;

// testdb.item中數(shù)據(jù)示例如下
 ------------------- ---------------- 
| no| fee_rate|
 ------------------- ---------------- 
| 1| 0.000000|
| 2| 0.000000|
| 3| 0.000000|
 ------------------- ---------------- 

3.將testdb.item中的數(shù)據(jù)保存到testdb.test_decimal中

// tmp是上述查詢testdb.item獲得的臨時表 // 以parquet格式保存到test_decimal的20200529分區(qū)中 save overwrite tmp as parquet.`/data/test_decimal/dt=20200529`; 
msck repair TABLE testdb.item;

上述1-3都能成功執(zhí)行,數(shù)據(jù)也能保存到testdb.test_decimal中,但是當查詢testdb.test_decimal中的數(shù)據(jù)時,比如執(zhí)行sql:

select * from testdb.test_decimal where dt = 20200529;

會報如下空指針的異常:

Job aborted due to stage failure: Task 0 in stage 4.0 failed 1 times, most recent failure: Lost task 0.0 in stage 4.0 (TID 4, localhost, executor driver): java.lang.NullPointerException at org.apache.spark.sql.hive.HiveShim$.toCatalystDecimal(HiveShim.scala:107)
  at org.apache.spark.sql.hive.HadoopTableReader$$anonfun$14$$anonfun$apply$11.apply(TableReader.scala:415)
  at org.apache.spark.sql.hive.HadoopTableReader$$anonfun$14$$anonfun$apply$11.apply(TableReader.scala:414)
  at org.apache.spark.sql.hive.HadoopTableReader$$anonfun$fillObject$2.apply(TableReader.scala:443)
  at org.apache.spark.sql.hive.HadoopTableReader$$anonfun$fillObject$2.apply(TableReader.scala:434)
  at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
  at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
  at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source)

究其原因是因為按照上述兩個參數(shù)的配置,testdb.item中fee_rate字段類型為decimal(10,6),數(shù)據(jù)為0.000000,經(jīng)過一系列處理0.000000最終會被處理為0,看下邊最終導(dǎo)致空指針異常的部分,就會一目了然。

public static BigDecimal enforcePrecisionScale(BigDecimal bd, int maxPrecision, int maxScale) { if (bd == null) { return null;
        } else {
            bd = trim(bd); if (bd.scale() > maxScale) {
                bd = bd.setScale(maxScale, RoundingMode.HALF_UP);
            } // testdb.test_decimal中fee_rate的類型decimal(10,10),即precision為10,scale也為10 // 對應(yīng)這里即maxPrecision和maxScale分別為10,則maxIntDigits為0 int maxIntDigits = maxPrecision - maxScale; // bd對應(yīng)0。對于0而言,precision為1,scale為0 // 處理之后 intDigits為1 int intDigits = bd.precision() - bd.scale(); return intDigits > maxIntDigits ? null : bd;
        }
}

解決辦法也很簡單,就是將testdb.test_decimal中的fee_rate數(shù)據(jù)類型和依賴的表testdb.item中的fee_rate保持完全一致,即也為decimal(10,6)。

這個現(xiàn)象在實際應(yīng)用環(huán)境中經(jīng)常遇到,通用的解決辦法就是將要保存的表中的數(shù)據(jù)類型與依賴的表(物理表或者臨時表)的字段類型保持完全一致。

 

 

 

 

更多關(guān)于云服務(wù)器域名注冊,虛擬主機的問題,請訪問三五互聯(lián)官網(wǎng):www.shinetop.cn

贊(0)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享網(wǎng)絡(luò)內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。郵箱:3140448839@qq.com。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明出處:三五互聯(lián)知識庫 » SparkSQL與Hive metastore Parquet轉(zhuǎn)換

登錄

找回密碼

注冊

主站蜘蛛池模板: 男女裸交免费无遮挡全过程| 久久亚洲精品中文字幕波多野结衣| 无码精品一区二区免费AV| 迁西县| 性色av蜜臀av色欲av| 一个人在看www免费| 一边捏奶头一边高潮视频| 亚洲大尺度无码无码专线| 亚洲精品日韩在线观看| 97久久综合亚洲色hezyo| 亚洲国产在一区二区三区| 天天弄天天模| 国产互换人妻xxxx69| 人妻中文字幕精品一页| 国产最新AV在线播放不卡| 大尺度国产一区二区视频 | 99久久亚洲综合精品网| 亚洲精品国产一区二区在线观看| 67194熟妇在线观看线路| 国精品午夜福利视频| 麻豆tv入口在线看| 国产欧美日韩视频一区二区三区| 国产中文字幕精品在线| 国自产拍偷拍精品啪啪一区二区| 中文字幕乱码在线播放| 在线播放亚洲成人av| 国产va免费精品观看| 日本精品不卡一二三区| 亚洲免费视频一区二区三区| 亚洲中文字幕无码专区| 国产精品亚洲二区在线播放| 亚洲中文字幕精品第三区| 国产日产欧产系列| 好男人社区在线www| 国产美女高潮流白浆视频| 靖西县| 激情国产一区二区三区四| 午夜国产精品福利一二| 国产亚洲av手机在线观看| 亚洲一线二线三线品牌精华液久久久| 日韩一欧美内射在线观看|