Hive底層文件存儲類型parquet

Hive作爲數據倉庫常用工具之一,在數據量級越來越大的時候,存儲問題會暴露出來。那麼在之前大部分爲了省事方便都會以TextFile*作爲存儲類型,此類型比較佔存儲,並且查詢效率並不是很高。爲了節省集羣的存儲空間,研究了各種存儲類型,網上各類帖子已經把這幾類的優缺點和使用場景說的非常明確。我在這稍微提及一下,主要想分享我在使用sqoop抽取數據時進行文件類型轉換(parquet)遇到的坑,共享出來希望遇到此問題的朋友借鑑,減少不必要時間消耗。*

一、概述一下各類文件類型的優缺點

1.TextFile

行存儲,直接存儲文件,數據量級大,磁盤開銷大,
優點:數據操作方便,直接使用put上傳數據文件,並且可以直接使用cat 查看HDFS上的文件內容

2.SequenceFile

行存儲,含有鍵值對的二進制文件,數據量級大,對於Hadoop生態系統之外的工具不適用,需要通過text文件轉化加載。
優點:可壓縮、可分割,優化磁盤利用率和I/O

3.rcfile

行列式存儲,先將數據按行分塊,同一個record在一個塊上,避免讀一條記錄需要讀多個block;然後塊數據列式存儲
缺點:加載時性能消耗較大,需要通過text文件轉化加載;讀取全量數據性能低(掃描的數據塊多效率低 )
優點:可壓縮,高效的列存取;查詢效率較高。

4.orcfile

列式存儲,優化後的rcfile,存儲方式和 rcfile 相同
優點:壓縮快,快速列存取 ,效率比rcfile高 ,上層presto查詢引擎和orc格式兼容性較好
缺點:查詢引擎不支持 impala 只能用hive查詢數據

5.parquet

列存儲Parquet僅僅是一種存儲格式,和語言、平臺無關,並且不需要和任何一種數據處理框架綁定,通常使用的查詢引擎和計算框架都已適配,並且可以很方便的將其它序列化工具生成的數據轉換成Parquet格式。
優點:
1.支持多種(幾乎大部分)查詢引擎,計算框架,數據模型
2.可以使用更多的壓縮算法
3.很好的支持: hive,spark,hadoop streaming,mapreduce,impala
4.查詢性能和壓縮比雖然沒有ORC高但是已經達到相對滿意的程度了


       如果使用impala組件,使用parquet 存儲格式是最好的搭配。根據實際使用情況得知: 使用parquet格式沒有采用壓縮就已經有 2.3:1 的壓縮比了 ,數據量至少比原來減少一半以上,並且不影響原來的查詢和計算。

二、sqoop+hive(parquet)

1.hive建表語句

CREATE TABLE database.table_tmp(
a bigint
b string,
c double
) 
PARTITIONED BY (etl_month string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (   'field.delim'='\t',   'line.delim'='\n',   'serialization.format'='\t') 
STORED AS INPUTFORMAT  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION 'hdfs://nameservice1/user/hive/warehouse/database.db/table_tmp'
TBLPROPERTIES('parquet.compression'='SNAPPY');

2.sqoop抽取數據配置

#啓用壓縮開關參數  --compress 
#壓縮格式定義  --compression-codec org.apache.hadoop.io.compress.SnappyCodec
#採用parquet文件存儲格式  --as-parquetfile
 
#數據抽取
sqoop import \
--append \
--connect "jdbc:sqlserver://$ip:$port;database=$source_db;username=$username;password=$password" \
--fields-terminated-by "${separator}"  -m 3 \
--query "${query}" \
--split-by "${split_col}" \
--as-parquetfile \
--target-dir "hdfs://nameservice1/user/hive/warehouse/$target_db.db/$target_tablename/$partition=$DATATIME" \
--hive-drop-import-delims \
--null-string '\\N' --null-non-string '\\N'

3. 遇到的坑

A.使用sqoop 導入hive表中,查表報錯,無法查詢

原因分析:數據源的數據類型和parquet所支持的數據類型不完全一致,所以導致查詢時出現數據類型轉換異常

parquet 和 hive 的 字段類型映射關係如下:
BINARY -> STRING
BOOLEAN -> BOOLEAN
DOUBLE -> DOUBLE
FLOAT -> FLOAT
INT32 -> INT
INT64 -> BIGINT
INT96 -> TIMESTAMP
BINARY + OriginalType UTF8 -> STRING
BINARY + OriginalType DECIMAL -> DECIMAL

所以在parquet的數據類型中不支持存儲 timestamp 、decimal 類型,在具體任務執行時就會出現下面這幾種錯誤類型

錯誤 1 Cannot inspect org.apache.hadoop.io.LongWritable

數據源的數據類型和hive表定義的數據類型不匹配,比如數據源數據類型爲 bigint,hive表中數據類型爲 string。存在兩種數據類型不一致時就會報此問題

錯誤 2 java.lang.ClassCastException:org.apache.hadoop.io.LongWritable cannot be cast to org.apache.hadoop.hive.serde2.io.TimestampWritable

在這裏插入圖片描述
在parquet中timestamp類型是用int96存儲的,如果在執行hive建表時將表字段定義爲timestamp類型,那麼在查詢時會出現轉換異常錯誤,若將hive表字段變爲int96時,查詢結果回是時間的長整型表示形式:長度爲10位,即表示的是秒數,從1970年1月1日開始的。這種長整型格式在使用時還需要進行數據格式轉換,才能轉換成“yyyyMMdd”類型,所以我們採用的策略是:將timestamp類型從數據源頭抽取時就轉換爲string類型

錯誤 3 java.lang.ClassCastException:org.apache.hadoop.io.Text cannot be cast to org.apache.hadoop.io.LongWritable

在parquet中沒有DECIMAL數據類型,如果將hive表定義爲此類型,在查詢時也會報如下錯誤。所以可以採取的策略是:數據抽取時就將數據源頭的數據轉換爲float 和 double。避免查詢時報錯

>>>在這記錄一個Hue的數據顯示問題

當表中字段類型定義爲double時,Hue查詢數據可能會出現數據精度或者轉換問題的假象,表象如下:
在這裏插入圖片描述
但是在hive的cli界面查詢時數據是正常的,沒有出現精度損失問題。如下圖:
在這裏插入圖片描述
如果廣大網友有遇到此類問題並且知道原理務必留言評論告知,非常感謝!

B. sqoop 抽取數據顯示“從字符串轉換日期和/或時間時,轉換失敗”

看此問題一度會認爲是數據抽取時數據轉換出現錯誤,其實不然。數據是在sqoop抽取數據時數據切分時報錯,定義 “ -m 3 ” 後,數據會切分爲3塊以3個reduce進行輸出。上一步咱們已經把時間戳字段轉換成了string進行存儲,那麼在抽取切分時也應該定義爲相同類型,保持一致。 比如在數據抽取字段中使用 monitortime 字段,由於需要轉換,我們將其轉換爲 CONVERT(varchar(19),monitortime,120) 字符串 (我們的數據源頭是sql server數據庫),那麼在 sqoop 參數**–split-by** 中使用monitortime 不進行轉換時就會出現下圖的錯誤,避免錯誤就得在該參數中也進行時間格式轉換
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章