ELK系列(十三)、在Hive中操作ES的索引数据,创建/查询/更新/插入

16 篇文章 42 订阅
6 篇文章 7 订阅

本篇介绍如何在hive中查询、更新、插入ES数据,以及把数据从hive导入到es中。本方案适用于任何hive可以挂外表的数据库类型。

ELK系列(一)、安装ElasticSearch+Logstash+Kibana+Filebeat-v7.7.0

ELK系列(二)、在Kibana中使用RESTful操作ES库

ELK系列(三)、安装Logstash插件及打包离线安装包

ELK系列(四)、Logstash读取nginx日志写入ES中

ELK系列(五)、Logstash修改@timestamp时间为日志的产生时间

ELK系列(六)、修改Nginx日志为Json格式并使用Logstash导入至ES

ELK系列(七)、Filebeat+Logstash采集多个日志文件并写入不同的ES索引中

ELK系列(八)、使用Filebeat+Redis+Logstash收集日志数据

ELK系列(九)、配置ES和Kibana的用户密码

ELK系列(十)、ES中文分词器IK插件安装和配置远程词库热加载

ELK系列(十一)、ElasticSearch7.7.0插件es-head安装及使用

ELK系列(十二)、使用SQL查询ElasticSearch7.7.0

-----------------------------------------------在HIVE中操作ES----------------------------------------------

官方文档:https://www.elastic.co/guide/en/elasticsearch/hadoop/current/hive.html

下载:https://www.elastic.co/cn/downloads/past-releases#es-hadoop

参数:https://www.elastic.co/guide/en/elasticsearch/hadoop/current/configuration.html

环境

CDH-6.3.1

hive-2.1.1

ElasticSearch-6.6.2  (ES7.7一样的,因为之前用的ES6没升级,修改配置需要重启HIVE所以我就不用ES7演示了)

依赖

要在hive中查询操作ES需要先将ES的jar包放在hive的依赖环境中,这里有几种方式,首先下载jar包,到上面的链接中下载对应ES版本的elasticsearch-hadoop-hive-6.6.2.jar,然后到hive的lib下【/opt/cloudera/parcels/CDH/jars/commons-httpclient-3.1.jar】找到commons-httpclient-3.1.jar,待会讲为什么需要它。

在hive中添加外部jar包,hive中加载外部jar包的方式有几种:

1. hive shell中add jar

 session级别的配置,只在hive命令行生效,不需要重启服务。 

#在hive shell中:
#本地jar
add jar /home/tools/wyk/elasticsearch-hadoop-hive-6.6.2.jar;
add jar /home/tools/wyk/commons-httpclient-3.1.jar;
#或hdfs的jar包
add jar  hdfs://nameservice1/tmp/hive/elasticsearch-hadoop-hive-6.6.2.jar;
add jar  hdfs://nameservice1/tmp/hive/commons-httpclient-3.1.jar;

 

2. 启动hive shell时添加配置

 session级别的配置,只在hive命令行生效,不需要重启服务。

hive -hiveconf hive.aux.jars.path=/home/tools/wyk/elasticsearch-hadoop-hive-6.6.2.jar

3. 在hive-site.xml中添加配置

 服务级别的配置,在hive-shell和hiveserver2都可以生效,需要重启Hive。 

vim hive-site.xml

<property>
  <name>hive.aux.jars.path</name>
  <value>/path/elasticsearch-hadoop.jar</value>
  <description>A comma separated list (with no spaces) of the jar files</description>
</property>

4. 将jar放置在hive.aux.jars.path下【推荐

服务级别的配置,在hive-shell和hiveserver2都可以生效,需要重启Hive,

elasticsearch-hadoop-hive-6.6.2.jarcommons-httpclient-3.1.jar 放在hiveserver2节点的/home/public/java_project/udf/目录,此目录在CM中可配置,参数为hive.aux.jars.path

 

 为什么要添加httpclient的jar?

如果不加的话很可能会遇到下面的错误信息,将【/opt/cloudera/parcels/CDH/jars/commons-httpclient-3.1.jar】文件也通过上面的方式加到依赖中即可解决此问题:

java.lang.ClassNotFoundException: org.apache.commons.httpclient.protocol.ProtocolSocketFactory

Error: java.lang.RuntimeException: java.lang.NoClassDefFoundError: org/apache/commons/httpclient/protocol/ProtocolSocketFactory
	at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:157)
	at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:54)
	at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:465)
	at org.apache.hadoop.mapred.MapTask.run(MapTask.java:349)
	at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:174)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1875)
	at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:168)
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/httpclient/protocol/ProtocolSocketFactory
	at org.elasticsearch.hadoop.rest.commonshttp.CommonsHttpTransportFactory.create(CommonsHttpTransportFactory.java:40)
	at org.elasticsearch.hadoop.rest.NetworkClient.selectNextNode(NetworkClient.java:102)
	at org.elasticsearch.hadoop.rest.NetworkClient.<init>(NetworkClient.java:85)
	at org.elasticsearch.hadoop.rest.NetworkClient.<init>(NetworkClient.java:61)
	at org.elasticsearch.hadoop.rest.RestClient.<init>(RestClient.java:94)
	at org.elasticsearch.hadoop.rest.InitializationUtils.discoverNodesIfNeeded(InitializationUtils.java:90)
	at org.elasticsearch.hadoop.rest.RestService.createWriter(RestService.java:581)
	at org.elasticsearch.hadoop.mr.EsOutputFormat$EsRecordWriter.init(EsOutputFormat.java:173)
	at org.elasticsearch.hadoop.hive.EsHiveOutputFormat$EsHiveRecordWriter.write(EsHiveOutputFormat.java:58)
	at org.apache.hadoop.hive.ql.exec.FileSinkOperator.process(FileSinkOperator.java:769)
	at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:882)
	at org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:95)
	at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:882)
	at org.apache.hadoop.hive.ql.exec.TableScanOperator.process(TableScanOperator.java:130)
	at org.apache.hadoop.hive.ql.exec.MapOperator$MapOpCtx.forward(MapOperator.java:146)
	at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:484)
	at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:148)
	... 8 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.httpclient.protocol.ProtocolSocketFactory
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 25 more

验证

通过上面第四种方式将jar放放置在hs2节点的hive.aux.jar.path路径下并重启Hive之后即可生效,在HUE中也可以直接通过Hive操作ES了。

hive建表属性

建表的TBLPROPERTIES中的属性可以在官网文档中查看:hive建表配置

...
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES ( 
'es.index.auto.create'='false',--自动创建索引
'es.index.read.missing.as.empty'='true', --防止查询为空值报错
'es.mapping.names'='id:id,name:name,age:age,pt:pt', --hive字段对应的ES字段,手动指定或自动映射
'es.mapping.id'='id', --指定hive的字段对应es索引的_id值
'es.resource'='wyk_csdn/_doc'  --ES中的索引
'es.net.http.auth.pass'='ES密码', --ES密码
'es.net.http.auth.user'='ES登录名', --ES登录名
'es.nodes'='localhost',  --ES地址
'es.port'='9200', 
'es.nodes.wan.only'='true', 
'es.nodes.discovery' = 'false',
'es.read.metadata'='true'
)

 

类型映射规则

hive中建表的时候可以不指定字段映射,也可以手动指定字段的类型映射,不指定的话会自动映射字段类型,映射规则如下:

hive和ES类型映射规则
Hive typeElasticsearch type
voidnull
booleanboolean
tinyintbyte
smallintshort
intint
bigintbigint
doubledouble
floatfloat
stringstring
binarybinary
timestampdate
structmap
mapmap
arrayarray
unionnot supported (yet)
decimalstring
datedate
varcharstring
charstring

验证交互

在Hive中创建ES外表并在ES中创建索引并插入数据:

-- 在Hive中创建ES外表并在ES中创建索引并插入数据
DROP TABLE IF exists default.es_bigdata_csdn01;
CREATE EXTERNAL TABLE if not exists default.es_bigdata_csdn01 (
 name string,
 age bigint,
 email string
)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.resource' = 'wyk_hive_csdn01/_doc',
'es.index.auto.create' = 'true', --自动建index
'es.index.read.missing.as.empty'='true',
'es.nodes' = '10.1.174.10',
'es.port'='9200'
);
-- 此时建完hive表,在es中没有索引
-- 插入一条数据后,在es中才能看到该索引
insert into default.es_bigdata_csdn01 values('王义凯',28,'wyk@csdn.com');

建hive外表读ES中已有的索引:

-- 建hive外表读已有的索引
CREATE EXTERNAL TABLE if not exists default.es_bigdata_csdn02(
 name string,
 age bigint,
 email string
)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.resource' = 'wyk_hive_csdn01/_doc',
'es.index.auto.create' = 'false', --因为是已有索引,所以无需自动建,其实就算选择了自动建,也可以读到已有的数据
'es.index.read.missing.as.empty'='true',
'es.nodes' = '10.1.174.10',
'es.port'='9200'
);

 

hive建表的时候指定ES索引的id唯一键映射:

在上面的Kibana截图中可以看到这条通过hive插入的数据的_id 属性的值是自动生成的,那么如果我们想指定该_id列为hive表的name列,这样的话就可以通过hive对ES的数据进行更新了,因为ES中_id相同的内容会自动更新。

-- 在hive中建ES外表并指定主键_id的映射字段
CREATE EXTERNAL TABLE if not exists default.es_bigdata_csdn03 (
 name string,
 age bigint,
 email string
)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.resource' = 'wyk_hive_csdn03/_doc',
'es.index.auto.create' = 'true', --若es中没有wyk_hive_csdn03索引则自动创建(需要在hive中对该索引插入数据才会生效)
'es.mapping.id'='name', --指定_id对应hive表的name字段
'es.index.read.missing.as.empty'='true',
'es.nodes' = '10.1.174.10',
'es.port'='9200'
);

insert into default.es_bigdata_csdn03 values('王义凯',28,'wyk@csdn.com');

此时我们在Hive中对该记录进行更新,看看在ES中该记录会变成什么样,注意在hive中无法对ES表使用updatedelete命令,因此我们仍旧使用insert命令只要主键相同就会自动更新:

insert into default.es_bigdata_csdn03 values('王义凯',29,'wyk29@csdn.com');
insert into default.es_bigdata_csdn03 values('Rick.Wang',30,'rick30@csdn.com');

 全量覆盖 insert overwrite

效果等同于append,insert into,如果有相同主键则更新没有则insert。

--insert overwrite的效果等同于insert into
insert overwrite table default.es_bigdata_csdn03 select 'Rick.Wang',33,'rick33@csdn.com';

多类型测试

在hive中建一个测试表,类型丰富,测试在ES中自动映射之后的类型:

drop table if exists default.es_bigdata_csdn04;
CREATE  TABLE if not exists default.es_bigdata_csdn04(
 id bigint,
 str_type string,
 decimal_type decimal(5,2),
 double_type double,
 float_type float,
 ins_ts timestamp,
 arr array<string>
)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.resource' = 'wyk_hive_csdn04/_doc',
'es.index.auto.create' = 'true',
'es.mapping.id'='id',
'es.index.read.missing.as.empty'='true',
'es.nodes' = '10.1.174.10',
'es.port'='9200'
);
--插入记录
insert into default.es_bigdata_csdn04 select 1,'str',3.14,4.13333,1.3333444,current_timestamp(),array('str1','str2','str3');

注意这里插入数据的时候不能用insert ... values(), 因为带有集合类型的记录,只能用insert .. select ...的写法,否则会报下面的错误:

FAILED: SemanticException [Error 10293]: Unable to create temp file for insert values Expression of type TOK_FUNCTION not supported in insert/values

 

 

从hive将数据导入ES

这个就很简单了,到目前未知应该很多人都能想到了,其实就是按照hive源表结构创建hive外表连接ES,然后在hive中执行下面的命令即可:

insert into hive_es select * from hive_src_tbl;

hive连接ES索引的其他的注意事项

  1. 不支持update,delete,truncate命令;
  2. truncate命令对hive外表(不能对no-managed的表进行清空操作);
  3. truncate命令对hive内表(不支持清空non-native 非原生表);
  4. 删除hive中的表(无论是External表还是Internal表),都是只会删掉hive表,对ES中的索引无影响;
  5. insert overwrite 全表覆盖,效果等同于append,insert into,如果有相同主键则更新没有则insert;

 

希望本文对你有帮助,请点个赞鼓励一下作者吧~ 谢谢!

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王义凯_Rick

遇见即是缘,路过就给个评论吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值