目录
1、前言
工作中经常遇到需要从Elasticserch中读取或者写入的需求。本篇文章我们将介绍如何通过hive来读写Elasticserch,像操作hive本地表一样来对ES的数据进行读写操作,方便我们数据开发。
2、环境配置
hive集成ES需要添加对应的类库到hive环境中,ES官网已经为我们提供了相应的jar包,直接下载就可以了,需要注意的是jar包版本要和ES的版本一致,不然会报错。如下载6.6.1版本:
下载地址:https://www.elastic.co/cn/downloads/past-releases#es-hadoop
可以通过以下方式加载jar包到hive:
- 通过CLI命令行临时加载
首先将jar上传到hdfs hive > add jar hdfs://ip:port/user/hive/jar/elasticsearch-hadoop-6.6.1.jar;
- 加入配置文件永久使用
<property>
<name>hive.aux.jars.path</name>
<value>/path/elasticsearch-hadoop-6.6.1.jar</value>
<description>A comma separated list (with no spaces) of the jar files</description>
</property>
3、创建映射表
设置好相应的jar后,就可以创建hive映射ES的表了,hive字段名类型和ES保持一致,示例如下:
CREATE EXTERNAL table if not exists test.hive_es_test
( id string ,
name string,
age string
)COMMENT 'hive读写ES测试'
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES(
'es.nodes' = 'ip1:port1,ip2:port2,ip3:port3',--es节点和http端口
'es.resource' = 'index/type' --指定index/type
);
映射表创建好后就可以对数据进行读写了:
insert into table test.hive_es_test
select *
from test.test_data limit 100;
select * from test.hive_es_test;
注意:
hive不区分大小写,而ES是区分大小写的。elasticsearch-hadoop.jar始终将hive的列名转为小写,使用时需要注意
4、条件查询
默认查询会返回es的所有数据,如果我们想对查询数据做一些条件过滤,可以在建表时在TBLPROPERTIES里加入参数es.query,对数据进行条件查询。下面介绍三种方式:
-
uri查询
通过ES的uri查询API,如’es.query‘=’?uri_query‘
-
dsl查询
查询语句放在{}里,语法参考ES官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-request-body.html
-
外部文档查询
如果不是上述两种格式,则会将参数值解释为hdfs文件路径,我们可以在文件中写入uri或者dsl查询语句,动态加载查询语句
查询示例:
# uri (or parameter) query
es.query = ?q=age:24 ##年龄等于24的数据
# query dsl
es.query = { "query" : { "term" : { "age" : 24 } } } ##年龄等于24的数据
# external resource
es.query = /hdfs_path/myquery.json
5、动态写入或多个index
我们可以指定某个字段作为index的名称,在数据写入ES时,不同数据动态写入不同的index
CREATE EXTERNAL TABLE test
(
name STRING,
type STRING,
year STRING
)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES( 'es.resource' = 'my-index-{type}/doc' --根据type字段的值写入对应的index );
6、写入任务数控制
为了保证ES服务稳定,需要限制数据写入ES的速率。我们可以通过限制写入的并发任务数,来限制写入速度。hive底层map端只能通过文件的分割数确定map数量,当数据量不固定变化较大时,对于多次定时写入任务来说就不能保证固定的任务数限制。而reduce端可以指定最大任务数,所以我们通过sql转换来将数据写入任务在reduce端执行,具体方式我们可以通过下面两种方式:
- group by方式
group by所有字段,让数据写入ES任务在reduce执行,并设置reduce允许的最大任务数
set hive.exec.reducers.max=n--设置reduce最大任务数
-
distribute by方式
通过distribute by让任务在reduce端直型
distribute by round(pmod(rand()*100,n));--限制写入任务数为n
7、常用参数介绍
- es.mapping.names
如果hive和ES的字段名称不一致,可以通过设置该参数,指定hive列名和ES列明的对应关系,如:
'es.mapping.names' ='hive_column1:es_column1,hive_column2:es_column2'
- es.index.auto.create(默认true)
如果ES中不存在指定的index,true的情况下可以在写入数据时自动创建,否则会直接报错
- es.batch.size.bytes(默认值 1MB)
设置ES bulk API批量写入的大小,这里是对每个写入任务的设置的值。总写入大小需要乘以hadoop的任务数
- es.batch.size.entries(默认值1000)
设置ES bulk API批量写入的行数大小,这里是对每个写入任务的设置的值。总写入大小需要乘以hadoop的任务数。es.batch.size.bytes和es.batch.size.entries只要有一个满足bulk就会执行
- es.mapping.id
document id可以指定某个字段,不指定的话ES自动生成doc id。如:
es.mapping.id='name'
- 基础认证
如果ES集群设置了基础认证,可以通过下面参数指定用户名和密码
'es.net.http.auth.user'='userName', --用户名
'es.net.http.auth.pass'='password' --密码
8、错误总结
org.elasticsearch.hadoop.rest.EsHadoopParsingException: Cannot parse value [2017-11-01 09:05:46.583] for field [time]
建表加参数:es.mapping.date.rich =false