在研究hive的时候遇到一些问题,在oracle表中查询很正常,结果导入到hive中就很不理想。
究其原因其实是因为hive是解析文本文件导致无法处理带分隔符或者回车符或者特殊字符,转义字符等等问题。
因为oracle在存储数据的时候有自己的一套二进制流写入方法,对于特殊字符基本都支持。
所以在这里我研究了采用sqoop和hive来兼容这种方法:
第一步: 改造sqoop文件
sqoop在导入数据到HDFS imp命令是会在本地生成一个.java 文件 。我们在导入数据是从整个java文件开始入手。重写java文件里面的内容然后打包
比如我这里重写java文件中
TEST_TABLE_NAME.java
public static String getUrlEncoderString(String str) {
String resultstr = "";
if (null == str) {
return "";
}
try {
resultstr = java.net.URLEncoder.encode(str,ENCODE);
} catch (Exception e) {
return "";
}
return resultstr;
}
public void readFields(ResultSET __dbResults)throws SQLException{
this.__cur_result_set = __dbResults;
this.date1 = getUrlEncoderString(JdbcWritableBridge.readString(1,__dbResults));
this.date2 = getUrlEncoderString(JdbcWritableBridge.readString(2,__dbResults));
this.date3 = JdbcWritableBridge.readTimestamp(3,__dbResults));
编译该文件得到一个 sqoop_zcjar.jar
第二步:导入数据到HDFS
我这里是oracle数据库 提供为oracle脚本
>sqoop import --connect jdbc:oracle:thin*** --username TESTUSER--password TESllc --table TEST_TABLE_NAME \
-class-name TEST_TABLE_NAME --jar-file /home/test/sqoop_zcjar.jar --fields-terminate-by '\001' \
--target-dir /user/test/TEST_TABLE_NAME -m 1
成功导入后可以采用 hadoop fs -ls /user/test/ 查看到文件
第三步:创建hive表
hive>create table TEST_TABLE_NAME (data1 String,date2 String ,date3 Timestamp);
hive>load data inpath '/user/test/TEST_TABLE_NAME/part-m*' into table TEST_TABLE_NAME;
到这一步数据导入完成 ,这个时候我们查看数据是发现 TEST_TABLE_NAME表中数据都是 转码之后的字符。
第四步: 编写utf
import org.apache.hadoop.hive.ql.exec.UDF;
public final class getURLDecoder extends UDF {
public static String getURLDecoderString(String str) {
String resultstr = "";
if (null == str) {
return "";
}
try {
resultstr = java.net.URLDecoder.decode(str,ENCODE);
} catch (Exception e) {
return "";
}
return resultstr;
}
hive>add jar /run/jar/getURLDecoder.jar;
hive>CREATE TEMPORARY FUNCTION getURLDecoder AS 'hive.udf.getURLDecoder';
第五步:创建view
hive>CREATE VIEW TEST_view_NAME AS SELECT getURLDecoder(data1) data1,getURLDecoder(data2) data2,data3 FROM TEST_TABLE_NAME ;
这个时候我们select TEST_view_NAME 就发现跟oracle一样 可以存储下特殊字符了。