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

本篇介绍如何在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 type Elasticsearch type
void null
boolean boolean
tinyint byte
smallint short
int int
bigint bigint
double double
float float
string string
binary binary
timestamp date
struct map
map map
array array
union not supported (yet)
decimal string
date date
varchar string
char string

验证交互

在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,'[email protected]');

建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,'[email protected]');

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

insert into default.es_bigdata_csdn03 values('王义凯',29,'[email protected]');
insert into default.es_bigdata_csdn03 values('Rick.Wang',30,'[email protected]');

 全量覆盖 insert overwrite

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

--insert overwrite的效果等同于insert into
insert overwrite table default.es_bigdata_csdn03 select 'Rick.Wang',33,'[email protected]';

多类型测试

在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;

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

猜你喜欢

转载自blog.csdn.net/wsdc0521/article/details/106545107