es导出hive遇到的问题汇总

首先直接上干货:

步骤

  1. 导入elasticsearch-hadoop-hive-5.5.2.jar包
  2. 创建hive外部表,数据源设置为es中,添加相应的配置
  3. 创建内部表拉取数据
add jar file:///home/hadoop/liubx/elasticsearch-hadoop-hive-5.5.2.jar;
add jar  file:///home/hadoop/hive-1.2.1/lib/es-hadoop.jar;   #代码见后面

use estest;
drop table if exists ext_es_test;
CREATE EXTERNAL TABLE ext_es_test(
typeid string,
cs_app string,
ipAddress string,
createTime  timestamp
)
row format delimited fields terminated by '\t'  
collection items terminated by ',' 
map keys terminated by ':'
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES(
'es.nodes' = 'master:9200',
'es.index.auto.create' = 'false',
'es.mapping.date.rich' = 'true',
'es.date.format' = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd", 
'es.ser.reader.value.class' = 'fjjf.es.EsValueReader',
'es.resource' = 'buriedpointinfo_bumsg/',
'es.read.metadata' = 'true',
'es.mapping.names' = 'typeid:_metadata._type, cs_app:cs_app,ipAddress:ipAddress,createTime:createTime');

#注释:
'es.nodes'                  -- es连接node信息
'es.index.auto.create'      -- 是否自动创建索引 
'es.mapping.date.rich'      -- 是否启用date自动转换,json中没有时间类型,es封装了一个Date类型存放特定格式的时间字符串。可以通过mapping指定format
'es.date.format'            -- 自定义dateformat
'es.ser.reader.value.class'  -- 自定义reader,由于本地es中存放时间采用了("yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"),导出时hive只能选择一种类型存取timestamp或者date
'es.resource'            -- es索引        
'es.read.metadata'       -- 是否读取es元数据字段         
'es.mapping.names'         -- es 和hive  字段映射

#分页查询
select * from estest.ext_es_test_bumsg limit 10;

#创建内部表分页查询
drop table if exists itn_es_test;
create table itn_es_testas 
select * from estest.itn_es_test;

遇到的问题:

  1. es中字段较多,不需要导出所有字段。
    解决: 通过'es.mapping.names' 配置筛选所需要的字段。

  2. 在hadoop-2.8版本下导出的时候经常会报Error: java.lang.ClassNotFoundException: org.apache.commons.httpclient.util.xxxx,但是hive/lib目录下确实有该类。手动添加后还是无法解决
    解决: 将版本切到2.7不会出现该问题,但是根本原因还是没有找到,待解决。

20180402更新:
解决方法:


URL:
  http://master:8088/taskdetails.jsp?jobid=job_1517535406767_315524&tipid=task_1517535406767_315524_m_000137
-----
Diagnostic Messages for this Task:
Error: java.lang.ClassNotFoundException: org.apache.commons.httpclient.util.DateParseException
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
    at java.lang.Class.getConstructor0(Class.java:3075)
    at java.lang.Class.newInstance(Class.java:412)
    at org.elasticsearch.hadoop.util.ObjectUtils.instantiate(ObjectUtils.java:41)
    at org.elasticsearch.hadoop.util.ObjectUtils.instantiate(ObjectUtils.java:52)
    at org.elasticsearch.hadoop.util.ObjectUtils.instantiate(ObjectUtils.java:48)

尝试在hive命令行手动添加jar失效之后,对比了hadoop2.7和hadoop2.8的jar包内容。发现hadoop-2.8.1/share/hadoop/common/lib目录下少了commons-httpclient-3.1.jar,由于本地hadoop2.8是编译安装的,所以怀疑是编译安装的时候没有将该依赖包打进去,对比官方下载的hadoop2.8二进制包发现也没有该jar包。
通过查看hadoop-2.8。0的change-log(https://issues.apache.org/jira/browse/HADOOP-13382

image.png

接下来,只需将es-hadoop依赖的commons-httpclient jar加入到所有的hadoop节点即可。

  • hadoop classpath | tr ':' '\n'
image.png
  1. es中导出的Date类型数据既有时间戳也有日期字符串,在存取到hive的时候发现以下问题;

1)时间戳无法正常转换为时间戳
37304150-01-31 14:25:515:51.616
37301390-01-10 14:25:515:51.616
37300635-01-05 14:25:515:51.616
37289863-10-16 14:25:515:51.616
2)时间字符串无法正常转换为时间戳,会报类转换异常 TextWritable unable cast to TimestampWritable

解决: 通过指定'es.ser.reader.value.class' ,自定义reader处理该异常,将所有时间格式字符串统一格式输出。

通过查看elasticsearch-hadoop的源码,发现es-hadoop在解析Date类型的时候使用的是DatatypeConverter.parseDateTime(value)。(无法应对我们自定义的各种时间格式,甚至包括UTC时区的时间。)

源码地址:
https://github.com/elastic/elasticsearch-hadoop/blob/master/hive/src/main/java/org/elasticsearch/hadoop/hive/HiveValueReader.java

@Override
    protected Object parseDate(Long value, boolean richDate) {
        return (richDate ? new TimestampWritable(new Timestamp(value)) : processLong(value));
    }

    @Override
    protected Object parseDate(String value, boolean richDate) {
        return (richDate ? new TimestampWritable(new Timestamp(DatatypeConverter.parseDateTime(value).getTimeInMillis())) : parseString(value));
    }

源码修改(默认情况下richDate为true,如果为false,则时间戳会当作Long处理,时间字符串当作Text处理)

@Override
    protected Object parseDate(String value, boolean richDate) {
        Date d = null;

        if(StringUtil.isNotEmpty(dateFormat)) {
            try {
                if(value.length() == 13){
                    return new TimestampWritable(new Timestamp(Long.valueOf(value)));
                }else{
                    d = DateUtil.parseDate(value, Arrays.asList(dateFormat.split("\\|\\|")));
                }

            } catch (DateParseException e) {
                e.printStackTrace();
                System.out.println("parse failed please check the dateFormat");
            }
        } else {
            d = DdfatatypeConverter.parseDateTime(value).getTime();
        }
        return new TimestampWritable(new Timestamp(d.getTime()));
    }

    protected Object parseDate(long value, boolean richDate) {
        Date d = new Date(value);
        return new TimestampWritable(new Timestamp(d.getTime()));
    }
  1. 最后遇到一个小问题,idea打包jar的时候太大,上传服务器速度较慢,将一些依赖去除打包后解决。
    解决: 在pom.xml中指定scope为proviede,打包的时候忽略。
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch-hadoop</artifactId>
    <version>5.5.0</version>
    <scope>provided</scope>
</dependency>

总结:
es国内资料比较杂乱,很多都还是2.x的。
建议研读官方文档,es这块配置项比较多,而且很多功能也许在配置项中已经可以找到解决方案了,缺乏的是仔细去研读和加深理解。这个我自己也正在学习的路上,哈哈!
另外,es-hadoop导出性能一般,20m/s左右,3个节点。有待提升,有时间可以对比下es-spark和java api效果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354