hive默認分隔符引起的日志分割問題


Hive中的外部表

對於Hive中的外部表來說,因為表是外部的,Hive認為其並不擁有這份數據,刪除該表並不會真正刪除其中的數據,其中的表描述元信息會被刪除掉。
 
對數據進行分區后,對於管理表,可以將其顯示在hdfs目錄中,但是外部表目錄中不會真正存在數據,只能通過show partitions命令來顯示外部表的分區信息。
 
我們的外部表是通過dateid進行的partition,如何顯示某個partition外部表對應的location:
 
hive -e "describe extended xxx partition (dateid=20141230)"
 
顯示出來的信息大致如下:
field1 string
dateid string

# Partition Information
# col_name data_type comment

dateid string

Detailed Partition Information Partition(values:[20141230], dbName:logbase_db, tableName:logbase, createTime:1419984079, lastAccessTime:0, sd:StorageDescriptor(cols:[FieldSchema(name:doc, type:string, comment:null), FieldSchema(name:dateid, type:string, comment:null)], location:hdfs://ns1/xxx/20141230, inputFormat:com.inputformat.XXXInputFormat, outputFormat:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat, compressed:false, numBuckets:-1, serdeInfo:SerDeInfo(name:null, serializationLib:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, parameters:{serialization.format=1}), bucketCols:[], sortCols:[], parameters:{}, skewedInfo:SkewedInfo(skewedColNames:[], skewedColValues:[], skewedColValueLocationMaps:{}), storedAsSubDirectories:false), parameters:{numFiles=129, transient_lastDdlTime=1419984079, COLUMN_STATS_ACCURATE=false, numRows=-1, totalSize=170482370617, rawDataSize=-1})
Time taken: 0.994 seconds, Fetched: 9 row(s)
 
顯示出來某個partition對應的hdfs地址等,使用的InputFormat等詳細信息。
 
關於外部表創建的語句,完整內容大概如下:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
(col_name data_type, ...)
[PARTITIONED BY (col_name data_type, ...)]
[CLUSTERED BY (col_name, col_name, ...)]
[SORTED BY (col_name, col_name, ...)]
[ROW FORMAT row_formart]
[STORED AS file_format]
[LOCATION hdfs_path]
[AS select_statement]
 
當然,也可以通過使用Like復制一個已經存在的表定義:
 
CREATE [EXTERNAL] TABLE [IF NOT EXIST] table_name LIKE existing_table name
[LOCATION hdfs_path]
 
其中各個語句的含義如下:
 
  • CREATE TABLE:創建一個指定名字的表名。如果已經存在,使用IF NOT EXIST來忽略拋出的異常
  • EXTERNAL:創建一個外部表,也就是說在創建一個表的同時指定一個指向實際數據的路徑。
  • LIKE:允許復制一個已經存在的表的定義,而不復制表中已經存在的內容。
  • PARTITIONED BY:建立帶有分區的表。
  • CLUSTERED:對表和分區進行類聚操作。
  • SORT BY:根據某個字段進行排序,可以提高數據的查詢效率。
 
如果要使用特定的InputFormat,還需要加入下面的語句:
 
INPUTFORMAT 'xxxHiveInputFormat'
     OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
     LOCATION '/aaa/hive-table'
 
 
這樣就指定InputFormat和OutputFormat,以及外部表的Location。其中InputFormat與Hadoop中的略有不同,其中的RecordReader需要特殊繼承Hive中的
 
org.apache.hadoop.hive.ql.io.HiveContextAwareRecordReader
 
 
可以做一個Adaptor來將原有的RecordReader進行適配以滿足Hive查詢的要求。
 

Hive中的分隔符

 
hive 默認的字段分隔符為ascii碼的控制符\001,建表的時候用fields terminated by '\001',如果要測試的話,造數據在vi 打開文件里面,用ctrl+v然后再ctrl+a可以輸入這個控制符\001。按順序,\002的輸入方式為ctrl+v,ctrl+b。以此類推。
 
當前我們新建的Hive表中,默認fields terminated by沒有設置,那么就使用'\001'。
 
比如我們的一條日志,表面上看起來沒有問題:
cat a.log 
tp=imp^ti=1419076654^md=iPhone3,1^__tid=5zKN0REAy8M%253D^mh=640.00x960.00^me=7.1.2^mf=84fef4314602f88b90dad8f2a9d4b23dv1.1t1419076650kcom.qiyi.iphone^mk=1^plt=1^mn=iphone^m9=128f0ab5^os=i^mm=31.892004x119.898267x50.000000^mp=com.qiyi.iphone^e=i___m^mo=1^m5=9920F2E3-4BDB-430F-BCC3-6ACF6EC6F155^kt=mma^mt=1419076649529^a=UoNVX034P723^rawIp=222.185.12.59^mw=1^j=zh^k=2001515^av=11^ip=222.185.12.59^m0=604a45ed52a06f1535711e3c68a130f2edc^pf=c1^p=101324851^pu=m^pn=iphone^rt=2^uuid=9920f2e3-4bdb-430f-bcc3-6acf6ec6f155^po=http%3a%2f%2fmlt01.com%2fo.htm%3fpv%3d0%26sp%3d0%2c1195912%2c1199754%2c2213157%2c0%2c1%2c1^ag=34

 

 

但是通過cat -A(--show-all),就可以看出所有的隱藏字符:

 

 

cat -A a.log
tp=imp^ti=1419076654^md=iPhone3,1^__tid=5zKN0REAy8M%253D^mh=640.00x960.00^me=7.1.2^mf=84fef4314602f88b90dad8f2a9d4b23dv1.1t1419076650kcom.qiyi.iphone^mk=1^plt=1^mn=iphone^m9=128f0ab5^os=i^mm=31.892004x119.898267x50.000000^mp=com.qiyi.iphone^e=i___m^mo=1^m5=9920F2E3-4BDB-430F-BCC3-6ACF6EC6F155^kt=mma^mt=1419076649529^a=UoNVX034P723^rawIp=222.185.12.59^mw=1^j=zh^k=2001515^av=11^ip=222.185.12.59^m0=604a45ed52a06f15357^A11e^@^@^@^@3c68a130f2edc^pf=c1^p=101324851^pu=m^pn=iphone^rt=2^uuid=9920f2e3-4bdb-430f-bcc3-6acf6ec6f155^po=http%3a%2f%2fmlt01.com%2fo.htm%3fpv%3d0%26sp%3d0%2c1195912%2c1199754%2c2213157%2c0%2c1%2c1^ag=34$

 

 
而其中看到的^A就是'\001'的表示(實際上是一個字符),這樣外部表中該行數據^A前面的字符被截斷導致該行數據只能顯示前半部分。
 
最終的簡單解決方法便是重寫InputFormat,替換掉可能會導致問題的字符串特殊字符。
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM