美文网首页我爱编程
es导出hive遇到的问题汇总

es导出hive遇到的问题汇总

作者: nicklbx | 来源:发表于2018-04-01 01:10 被阅读0次

    首先直接上干货:

    步骤

    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效果。

    相关文章

      网友评论

        本文标题:es导出hive遇到的问题汇总

        本文链接:https://www.haomeiwen.com/subject/djtocftx.html