ES 总结
一 、es常用命令
--查看所有索引
curl -u elastic:Passw0rd -XGET xxx.xx.xxx:9200/_cat/indices?v
--查看指定索引的信息
curl -u elastic:Passw0rd -XGET http://xxx.xxx.xxx:9200/kgl_test?pretty
--查看指定索引结构信息
curl -u elastic:Passw0rd -XGET xxx.xx.xxx.xxx:9200/group_tag_all_boci_test?pretty=true&v&s=index
curl -u elastic:Passw0rd -XGET xxx.xx.xxx.xxx:9200/group_tag_all_boci_test?pretty
-- 查所有数据
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_test/_search?pretty -H 'Content-Type: application/json' -d'{"query": {"match_all":{}}}'
--指定客户所有标签名称
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_sc/_search?pretty -H 'Content-Type: application/json' -d'{"query": {"match_phrase": {"client_id": "12953399"}}}'
--指定客户及某几个标签,_source下需要填你想查的标签
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_sc/_search?pretty -H 'Content-Type: application/json' -d'{"query": {"match_phrase": {"client_id": "12953399"}} ,"_source":["client_id","client_membership_level","mbr_level","old_count_mbr_level","new_count_mbr_level","client_mbr_assets"]}'
查询一个用户某几个标签的样例,_source下需要填你想查的标签及对应的版本
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_sc/_search?pretty -H 'Content-Type: application/json' -d'{"version":true,"query": {"match_phrase": {"client_id": "12953399"}} ,"_source":["client_id","client_membership_level","mbr_level","old_count_mbr_level","new_count_mbr_level","client_mbr_assets"]}'
--指定条件数据数量
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci/_count?pretty -H 'Content-Type: application/json' -d'{"query": {"match_phrase": {"client_acted_task": "HDRW0988"}}}'
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci/_count?pretty -H 'Content-Type: application/json' -d'{"query": {"match_phrase": {"client_acted_task.keyword": "HDRW1393"}}}'
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci/_count?pretty -H 'Content-Type: application/json' -d'{"query": {"regexp": {"client_acted_task.keyword": {"value": ".*HDRW1393.*"}}}}'
-- 指定条件数据
curl -k -u elastic:Passw0rd -XPOST http://localhost:9200/kgl_test/_search?pretty -H 'Content-Type: application/json' -d'{"query": {"match_phrase": {"client_birthday_year": "2025"}}}'
--统计存在某个标签的 总数据量
curl -k -u elastic:Passw0rd -XGET http://IP地址:端口/group_tag_all_boci_sc/_count?pretty -H 'Content-Type: application/json' -d'{"query": { "bool": { "must": { "exists": {"field": "open_date"}}}}}'
--查索引总数据量
curl -k -u elastic:Passw0rd -XPOST http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_sc/_count--删除指定索引的指定数据 如53051459用户的所有标签
curl -k -u elastic:Passw0rd -XDELETE http://xxx.xx.xxx.xxx:9200/group_tag_all_boci/_doc/53051459
--删除指定索引所有数据
curl -u elastic:Passw0rd -XPOST 'http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_sc/_delete_by_query?pretty' -H 'Content-Type: application/json' -d '{"query":{"match_all":{}}}'
-- 删除索引
curl -u elastic:Passw0rd -XDELETE xxx.xx.xxx.xxx:9200/group_tag_all_boci_test-- 创建索引并自定义配置,创建名为 group_tag_all_boci 的索引,同时指定分片 / 副本配置和字段映射(mapping)
-- number_of_shards: 2(主分片数,创建后不可修改);number_of_replicas: 1(副本数,可后续修改)
-- 定义 4 个字段(client_task/stock_list/client_goods/client_active),均为「text+keyword 多字段类型」(支持全文检索 + 精确匹配)
-- ignore_above: 10240(keyword 字段忽略长度超过 10240 字符的内容,避免占用过多空间) ignore_above 仅对「新增文档」生效,历史文档不会自动更新
curl -k -u elastic:Passw0rd -H "Content-Type: application/json" -XPUT "http://xxx:9200/group_tag_all_boci" -d '{"settings":{"number_of_shards":2,"number_of_replicas":1},"mappings":{"properties":{"client_task":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":10240}}},"stock_list":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":10240}}},"client_goods":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":10240}}},"client_active":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":10240}}}}}}'
curl -k -u elastic:Passw0rd -H "Content-Type: application/json" -XPUT "http://xxx:9200/group_tag_all_boci/_mapping" -d '{"properties": {"discount_coup": { // 新增的字段名"type": "text", "fields": {"keyword": { // 子字段,用于精确查询"type": "keyword","ignore_above": 10240 // 超过该长度的内容不索引}}}}
}'
二、es 改索引别名
1 修改别名
curl -u elastic:Passw0rd -XPOST 'http://xxx.xx.xxx.xxx:9200/_aliases' -H 'Content-Type: application/json' -d'{"actions": [{"add": {"index": "group_tag_all_boci_test_main", "alias": "group_tag_all_boci_test"}}]}'
curl -u elastic:Passw0rd -XPOST 'http://xxx.xx.xxx.xxx:9200/_aliases' -H 'Content-Type: application/json' -d'{"actions": [{"add": {"index": "group_tag_all_boci_test_back", "alias": "group_tag_all_boci_test"}}]}'
--目标索引:group_tag_all_boci_test_main group_tag_all_boci_test_back(实际存储数据的索引)新增别名:group_tag_all_boci_test(后续可通过别名访问索引,隐藏真实索引名)--验证别名是否创建成功
-- 查看单个别名关联的所有索引 添加 -s(静默模式,去除进度条)和 | jq(格式化 JSON 响应)
curl -u elastic:Passw0rd -s -XPOST 'http://xxx.xx.xxx.xxx:9200/_alias/group_tag_all_boci_test' | jq
curl -u elastic:Passw0rd -XGET 'xxx.xx.xxx.xxx:9200/_alias/group_tag_all_boci_test'
-- 查看索引关联的所有别名
curl -u elastic:Passw0rd -s -XPOST 'http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_test_main/_alias' | jq
curl -u elastic:Passw0rd -s -XGET 'xxx.xx.xxx.xxx:9200/group_tag_all_boci_test_main/_alias'
-- 3. 查看所有别名(全局遍历,快速核对)
curl -u elastic:Passw0rd -s -XGET 'xxx.xx.xxx.xxx:9200/_cat/aliases?v'
- 批量操作(添加 + 删除别名)
支持在一个请求中执行多个动作(如给新索引添加别名,同时删除旧索引的别名):
curl -u elastic:Passw0rd -s -XPOST 'http://xxx.xx.xxx.xxx:9200/_aliases' \
-H 'Content-Type: application/json' \
-d '{"actions": [# 删除旧索引的别名(可选){"remove": {"index": "group_tag_all_boci_test_main", "alias": "group_tag_all_boci_test"}},# 添加新索引的别名{"add": {"index": "group_tag_all_boci_test_back", "alias": "group_tag_all_boci_test"}}]
}' | jq
3 删除主索引数据
curl -u elastic:Passw0rd -XPOST 'http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_test_main/_delete_by_query?pretty' -H 'Content-Type: application/json' -d '{"query":{"match_all":{}}}'
4 更新
– 移除旧索引 group_tag_all_boci_test_back 与别名 group_tag_all_boci_test 的关联
– 同时将别名 group_tag_all_boci_test 绑定到新索引 group_tag_all_boci_test_main(常用于索引平滑切换,如数据迁移后切换读写入口,对业务无感知)
curl -u elastic:Passw0rd -XPOST 'http://xxx.xx.xxx.xxx:9200/_aliases' -H 'Content-Type: application/json'
-d'{"actions": [# 删除旧索引的别名(可选){"remove": {"index": "group_tag_all_boci_test_back","alias": "group_tag_all_boci_test","must_exist": true // 若旧索引未关联该别名,会报错终止操作(避免误操作) --可选,按需启用}},# 添加新索引的别名{"add": {"index": "group_tag_all_boci_test_main","alias": "group_tag_all_boci_test"}}
]
}'
-- 切换后未移除旧关联,手动删除旧关联
curl -u elastic:Passw0rd -XPOST 'http://xxx.xx.xxx.xxx:9200/_aliases' -d '{"actions": [{"remove": {"index": "group_tag_all_boci_test_back", "alias": "group_tag_all_boci_test"}}]}'
5备份
– 索引group_tag_all_boci_test_main数据到备份索引group_tag_all_boci_test_back
– 将源索引 group_tag_all_boci_test_main 的全部数据复制到目标索引 group_tag_all_boci_test_back(通常用于数据备份、索引结构迁移等场景)
– 操作类型:_reindex(Elasticsearch 内置 API,用于跨索引数据迁移)
– 源索引:group_tag_all_boci_test_main(待复制数据的原索引)
– 目标索引:group_tag_all_boci_test_back(接收数据的目标索引,无需提前创建,ES 会自动创建默认结构)
curl -u elastic:Passw0rd -POST 'http://xxx.xx.xxx.xxx:9200/_reindex' -H 'Content-Type: application/json' -d'{
"source": {"index": "group_tag_all_boci_test_main"},
"dest": {"index": "group_tag_all_boci_test_back"}
}'
6 执行结果验证
重索引完成后,可通过以下命令验证数据一致性:
-- 1. 对比源索引和目标索引的文档数
curl -u user:password -s 'http://xxx.xx.xxx.xxx:9200/_cat/indices/group_tag_all_boci_test_main,group_tag_all_boci_test_back?v' | grep -E "docs.count|group_tag"
-- 2. 随机查询目标索引的文档,确认数据正确
curl -u user:password -s 'http://xxx.xx.xxx.xxx:9200/group_tag_all_boci_test_back/_search?size=1' | jq '.hits.hits[0]._source'
insert overwrite table tmp.group_tag_all_boci_test_main
select '1001' as client_id,'kgl1' as name,101 as age
union all
select '10011' as client_id,'kgl11' as name,1011 as age;
insert overwrite table tmp.group_tag_all_boci_test_back
select '1002' as client_id,'kgl2' as name,102 as age
union all
select '10022' as client_id,'kgl22' as name,1022 as age;
三、创建 es-hadoop表
如果es没有提前通过curl创建索引时,想要自动创建 需要开启动态映射
ES默认动态映射为true,若之前手动关闭过,需重新开启:
curl -u user:password -H "Content-Type: application/json" -XPUT "http://es-host:9200/group_tag_all_boci_v2/_settings" -d '{"index.mapper.dynamic": "true" # 允许 ES 自动创建未定义的字段映射
}'
–查询索引的动态映射配置
curl -u user:password -s "http://es-host:9200/group_tag_all_boci_v2/_settings/index.mapping.dynamic?pretty" | jq
curl -u elastic:Passw0rd -XGET es-host:9200/group_tag_all_boci_test_back/_settings/index.mapping.dynamic?pretty
--查看单个索引完整映射相关配置(含dynamic、date_detection等)
curl -u user:password -s "http://es-host:9200/group_tag_all_boci_v2/_settings?pretty" | jq '.group_tag_all_boci_v2.settings.index.mapping'
curl -u elastic:Passw0rd -s "es-host:9200/group_tag_all_boci_test/_settings?pretty"
--查看多个索引动态映射配置
curl -u user:password -s "http://es-host:9200/group_tag_all_boci_v2,group_tag_all_boci_test_main/_settings/index.mapping.dynamic?pretty" | jq
drop table if exists tmp.group_tag_all_boci_test_main;
create table tmp.group_tag_all_boci_test_main (
client_id string comment 'khh',
name string comment '姓名',
age string comment '年龄'
)
ROW FORMAT SERDE 'org.elasticsearch.hadoop.hive.EsSerDe'
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.index.read.missing.as.empty'='true', -- 缺失索引读为空(去重)
'es.field.read.empty.as.null' = 'true', -- 空字段读为NULL
'es.mapping.id'='client_id', -- 文档唯一ID,必选 与ES映射的client_id对应
'es.write.operation'='upsert', -- 存在则更新,不存在则插入
-- 'es.write.dynamic'='strict', -- 严格字段映射,避免类型不匹配
'es.net.http.auth.user'='elastic', -- 认证用户
'es.net.http.auth.pass'='Passw', -- 认证密码
'es.nodes'='xxx.xx.xxx.xxx:9200,xxx.xx.248.1:9200,xxx.xx.248.2:9200', -- 集群节点
'es.index.auto.create'='true', -- 自动创建索引(生产建议提前创建) false关闭自动创建索引(关键!使用手动创建的索引)
'es.nodes.wan.only'='true', -- 跨网段/WAN环境必开
'es.read.metadata'='true',
'es.resource'='group_tag_all_boci_test_main/_doc', -- 索引/类型
'es.index.read.missing.as.empty'='yes',
'es.batch.size.bytes' = '2097152', -- 单批大小(默认1MB,推荐写法)
-- 'es.batch.size.bytes' = '2mb', -- 单批大小(默认1MB es大小写敏感)
'es.batch.size.entries' = '2000', -- 单批条目(不写默认1000,提升吞吐量)
-- 高版本ES适配(若集群>7.x)
-- 'es.nodes.discovery'='false', -- 关闭自动发现,强制用配置节点
-- 'es.net.ssl.enabled'='true', -- 若启用SSL,需同步开启(你的原配置有ssl协议)
-- 'es.net.ssl.protocol'='TLSv1.2' -- 明确SSL协议版本
'es.net.ssl.protocol'='ssl');–如果想保存es重复数据drop table if exists tmp.group_tag_all_boci_test_main;
create table tmp.group_tag_all_boci_test_main (
client_id string comment 'khh',
name string comment '姓名',
age string comment '年龄'
)
ROW FORMAT SERDE 'org.elasticsearch.hadoop.hive.EsSerDe'
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.index.read.missing.as.empty'='true',
'es.field.read.empty.as.null' = 'true',
-- 移除文档ID映射(或改为非唯一字段),避免ES按固定ID去重
-- 原配置:'es.mapping.id'='client_id',
'es.write.operation'='index', -- 保持普通插入,不触发更新逻辑
'es.net.http.auth.user'='elastic',
'es.net.http.auth.pass'='Passw0rd',
'es.nodes'='xxx.xx.xxx.xxx:9200,xxx.xx.248.1:9200,xxx.xx.248.2:9200',
'es.index.auto.create'='true',
'es.nodes.wan.only'='true',
'es.read.metadata'='true',
'es.resource'='group_tag_all_boci_test_main/_doc',
'es.nodes.wan.only' = 'true',
'es.index.read.missing.as.empty'='yes',
'es.net.ssl.protocol'='ssl');
注意
'es.write.operation'='upsert'
'es.write.operation'='index'
--表已创建
-- 示例1:将写入逻辑改为index(全量覆盖)
ALTER TABLE jgcrm_t_corp_dd_to_es SET TBLPROPERTIES ('es.write.operation'='index');
-- 示例2:将写入逻辑改为upsert(增量更新)
ALTER TABLE jgcrm_t_corp_dd_to_es SET TBLPROPERTIES ('es.write.operation'='upsert');
--index 操作在 _id 存在时会覆盖整个文档(旧文档被删除,新文档插入),而 upsert 是增量更新(仅修改指定字段,保留未更新的原有字段),更适合需要保留历史字段的场景。取值 不存在对应文档时 存在对应文档时 核心特点 适用场景
index 插入新文档 完全覆盖原有文档(删除未出现字段) 全量同步,数据强一致 每日全量更新、数据重刷
upset 插入新文档 仅更新非空字段(保留未覆盖字段) 增量同步,保留历史字段 部分字段更新、增量数据补全
es.write.operation是控制数据写入Elasticsearch时操作类型的配置参数,当设置为’index’时,其含义如下:
操作行为:表示执行「索引」操作。如果文档的_id不存在,则会创建新文档;如果_id已存在,则会覆盖(更新)现有文档(相当于先删除旧文档,再插入新文档,版本号会递增)。
与其他操作的区别:
若设为’create’:仅在_id不存在时创建文档,若_id已存在则会报错(避免覆盖)。
若设为’update’:仅更新已存在的文档(需配合_id使用),若_id不存在可能报错(具体取决于工具实现)。
若设为’upsert’:结合了update和create,_id存在则更新,不存在则创建新文档。
'index’是比较常用的默认行为之一,适用于需要「有则更新、无则创建」的场景,例如日志同步、数据全量覆盖更新等。
在Elasticsearch中,upsert和index操作的插入效率(针对「文档不存在时的创建场景」)基本接近,但在「文档已存在时的处理场景」中,两者的效率差异较明显,主要取决于操作逻辑的复杂度:
1、当文档不存在时(创建新文档)
index操作:直接创建新文档(本质是create逻辑),仅需写入一次数据。
upsert操作:因_id不存在,执行预定义的「插入逻辑」(如使用upsert模板创建文档),同样是写入一次数据。
结论:此时两者效率几乎无差异,均为一次写入操作,性能取决于数据大小和集群负载。
2、当文档已存在时(处理已有文档)
index操作:执行「覆盖式更新」——先删除旧文档,再插入新文档(本质是delete+create的组合)。此过程会生成新的文档版本,旧文档被标记为删除(后续由段合并清理),但操作逻辑简单,仅需处理一次完整文档写入。
upsert操作:执行「增量更新」——仅更新指定字段,保留未修改的原有字段(本质是update逻辑)。此过程需要先读取旧文档的内容,合并新字段后再写入,涉及「读+写」两次I/O操作(即使启用了retry_on_conflict重试机制,逻辑更复杂)。
结论:index效率通常高于upsert,因为upsert多了一次读取旧文档的开销,尤其在文档体积较大或更新频繁时,差距更明显。
在Hive与Elasticsearch(ES)的关联场景中,默认情况下删除Hive表不会影响ES数据,但存在一种特殊情况可能导致删除Hive表时间接删除ES数据:
仅当满足以下条件时,删除Hive表可能触发ES数据删除:
Hive表使用ESStorageHandler且配置了es.index.auto.create:false即ES索引由Hive表创建并强绑定(索引不存在时不会自动创建,需通过Hive表定义关联已存在的索引)。
Hive表是ES索引的唯一“管理入口”且删除操作被二次开发拦截某些业务场景中,可能通过自定义脚本或工具对Hive的DROPTABLE操作进行拦截,在删除Hive表的同时,自动调用ES的删除API(如DELETE/index)删除对应的ES索引。这种情况属于人为定制的联动逻辑,而非Hive或ES的原生功能。
注意:
原生机制下无联动删除:Hive与ES本身是独立系统,Hive的DROPTABLE命令仅操作Hive元数据和自身存储(如HDFS),不会主动通知ES删除数据。
ES数据删除依赖显式操作:若需删除ES数据,需单独通过ES的API、Kibana或工具执行删除索引/文档的操作。
因此,删除Hive表导致ES数据删除的情况,仅可能出现在人为定制的联动逻辑中,而非默认行为。
在Hive中,external.table.purge是一个表属性参数,主要用于控制删除Hive外部表时,是否同时删除外部存储系统中的数据(如HDFS、Elasticsearch、S3等外部存储的数据)。
参数含义与作用
参数值:TRUE或FALSE(默认通常为FALSE)。
核心逻辑:
当external.table.purge=TRUE时:删除Hive外部表(DROPTABLE)时,Hive会尝试删除外部存储中对应的数据(如HDFS上的文件、ES中的索引等,具体取决于外部存储类型)。
当external.table.purge=FALSE时(默认):删除Hive外部表仅会移除Hive的元数据(表定义),不会影响外部存储中的实际数据。
注意事项
外部表的本质:Hive外部表(EXTERNALTABLE)的设计初衷是“数据独立于Hive管理”,即数据存储在Hive之外的系统(如HDFS、ES、S3),Hive仅维护表结构的元数据。因此,默认情况下(purge=FALSE),删除外部表不会触碰外部数据,避免误删重要数据。
兼容性与局限性:
该参数的效果依赖于外部存储系统的支持。例如:
对于HDFS上的外部表:purge=TRUE会删除HDFS路径下的数据文件。
对于Elasticsearch关联的外部表:purge=TRUE理论上可能尝试删除ES索引,但实际是否生效取决于Hive与ES的连接器(如elasticsearch-hadoop)是否支持该操作,且需确保Hive有ES的删除权限(通常不建议依赖此参数删除ES数据,风险较高)。
部分外部存储(如关系型数据库、Kafka)可能完全不支持通过该参数删除数据,此时purge=TRUE可能无效。
风险提示:
生产环境中不建议轻易设置external.table.purge=TRUE,尤其是关联重要外部数据(如ES索引、生产库表)时,可能因误删Hive表导致外部数据丢失,且难以恢复。
若需删除外部存储的数据,建议通过外部系统自身的工具或API(如ES的DELETE/index、HDFS的hdfsdfs-rm)显式操作,更安全可控。
总结
external.table.purge是Hive为外部表提供的“元数据与外部数据联动删除”开关,默认关闭(不删除外部数据)。使用时需谨慎,尤其是关联非HDFS的外部存储(如ES)时,其效果可能不稳定,且存在数据误删风险,建议优先通过外部系统自身工具管理数据生命周期。
四、es优化
Elasticsearch-Hadoop(ES-Hadoop)本身不直接设置副本数,写入时使用的副本数由目标 Elasticsearch 索引的配置决定。
ES 索引的默认副本数为 1 个(即 number_of_replicas: 1),这是 Elasticsearch 对所有新建索引的默认配置,与是否通过 ES-Hadoop 写入无关。
关键说明:
副本数由索引自身配置决定无论通过 ES-Hadoop、REST API 还是其他客户端写入数据,副本数均由目标索引的 number_of_replicas 参数控制。例如:
若索引创建时未指定副本数,默认 number_of_replicas: 1;
若手动配置了索引(如 number_of_replicas: 2),则 ES-Hadoop 写入时会使用该配置。
如何查看或修改副本数可通过 ES API 查看或调整目标索引的副本数:
# 查看索引副本数
curl -XGET "http://es-host:9200/your_index/_settings?pretty"# 临时修改副本数(例如写入期间设为 0 提升性能,完成后恢复)
curl -XPUT "http://es-host:9200/your_index/_settings" -H "Content-Type: application/json" -d '
{"number_of_replicas": 0
}'
ES-Hadoop 与副本的关系ES-Hadoop 写入数据时,会遵循 ES 集群的副本同步机制:数据先写入主分片(primary shard),再同步到所有副本分片(replica shard)。副本数越多,写入耗时越长(需等待更多副本同步),因此在大批量写入场景中,常临时将副本数设为 0 以提升效率,完成后再恢复。
分片与副本配置:该索引采用 1 主 1 副 的配置(1 个主分片 + 1 个副本分片),适合数据量较小的场景(如小量表、配置表)。若未来数据量增长,单主分片可能成为性能瓶颈(建议主分片数根据预期数据量提前规划,通常单个分片容量控制在 20-50GB)。
副本数:副本数为 1,意味着数据会同步到 1 个副本分片,兼顾高可用(主分片故障时副本可切换)和写入性能(副本数越多,写入同步开销越大)。若需临时提升写入速度(如大批量导入数据),可临时将副本数改为 0,完成后再恢复为 1:
# 临时修改副本数为 0
curl -XPUT "http://es-host:9200/group_tag_all_boci/_settings" -H "Content-Type: application/json" -d '{"number_of_replicas": 0}'
# 恢复副本数为 1
curl -XPUT "http://es-host:9200/group_tag_all_boci/_settings" -H "Content-Type: application/json" -d '{"number_of_replicas": 1}'
curl -u elastic:Passw0rd -XGET xxx.xx.xxx:9200/_cat/indices?v
结果:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open group_tag_all_boci grN65MDQTrWPBb7pzr9ODw 1 1 6834114 2608272 42.5gb 22.8gb
1、主分片数(pri):
单主分片承载近 683 万文档(docs.count),存储约 22.8GB(pri.store.size)。
风险:单分片容量已接近 20-50GB 的合理上限(推荐值),若数据持续增长(如超过 50GB),会导致:
- 写入 / 查询性能下降(单分片压力集中);
- 分片恢复时间变长(故障时恢复慢);
- 无法水平扩展(主分片数创建后不可改)。
2、副本数(rep):
1个副本是平衡可用性和性能的合理配置(主分片故障时副本可切换,写入同步开销适中),暂时无风险。
3、文档数与删除数:
683 万文档,260 万删除 大量删除文档(docs.deleted)会导致分片内产生碎片,浪费存储空间并影响查询效率。
建议:
清理删除文档产生的碎片(通过 force-merge 操作):
# 强制合并分片,释放删除文档占用的空间(仅在低峰期执行)
curl -XPOST "http://es-host:9200/group_tag_all_boci/_forcemerge?max_num_segments=1"
(2)若数据量持续增长(如年增长 > 30GB)或查询压力大
当前配置不合适:单主分片会成为瓶颈,建议重建索引并增加主分片数(如 3-5 个,根据预期数据量评估)。
示例:新建索引 group_tag_all_boci_v2 并设置 3 个主分片:
# 创建新索引(3主1副)
curl -XPUT "http://es-host:9200/group_tag_all_boci_v2" -H "Content-Type: application/json" -d '
{"settings": {"number_of_shards": 3, # 主分片数增加到3"number_of_replicas": 1 # 副本数保持1},"mappings": { ... } # 复用原索引的映射
}'# 迁移数据(低峰期执行)
curl -XPOST "http://es-host:9200/_reindex" -H "Content-Type: application/json" -d '
{"source": { "index": "group_tag_all_boci" },"dest": { "index": "group_tag_all_boci_v2" }
}'
es.batch.size.entries和es.batch.size.bytes的最佳值需结合文档大小、ES集群性能、网络带宽综合调整,以下是基于前面信息的具体建议(结合你的索引和任务场景):
一、核心原则
批量大小需匹配ES处理能力:避免过大(如单次10MB以上会导致ES写入线程池队列满(es_rejected_execution_exception),过小过小则会增加请求overhead,降低吞吐量。
优先按bytes限制,辅助按entries限制:确保单批数据的物理大小可控,避免因大文档导致请求超时。
二、推荐配置(基于你的场景)
结合你的索引group_tag_all_boci数据量(单文档约3-10KB,估算)和ES集群情况(单分片、1副本),建议:
参数 推荐值 说明
es.batch.size.entries 1000-2000 单次批量写入1000-2000条文档(按单文档5KB计算,对应5-10MB)。
es.batch.size.bytes 10mb 单批数据大小不超过10MB(避免ES因请求过大拒绝,与entries形成双重限制)。
三、调整依据
文档大小估算:你的索引group_tag_all_boci总存储42.5GB,含683万文档,单文档平均大小约6-7KB(42.5GB÷683万≈6.5KB)。
若按1000条文档计算,单批大小约6.5MB(未超10MB),ES单分片可承载;
若调至2000条,单批约13MB(略超10MB),此时bytes限制会生效,自动截断为10MB左右,避免请求过大。
ES集群承受能力:你的ES集群当前为单分片,写入压力集中,若批量过大(如5000条)会导致:
单分片写入线程池拥堵(队列满);
批量请求超时(bulktimeout)。
因此需保守起步,逐步递增测试。
网络与超时配合:若网络带宽有限(如跨机房同步),建议bytes不超过5MB,避免网络传输超时;同时需延长超时配置:
es.http.timeout=60s#确保大批次请求有足够时间传输和处理
四、动态调整方法
起步测试:先用推荐值(entries=1000,bytes=10mb)运行任务,观察:
ES日志是否有rejectedexecution(队列满);
Hadoop任务日志是否有timeout(请求超时);
ES集群写入速率(通过_cat/indices观察docs.count增长速度)。
逐步递增:
若稳定无报错,可每次增加500条(entries),同时bytes增加5MB,直至出现轻微的队列等待(queuedtasks偶尔超过50),此时的前一个值即为最佳。
若出现拒绝请求,立即调小20%,并检查ES集群资源(CPU、I/O是否瓶颈)。
五、特殊场景优化
若文档较小(如1-2KB):可将entries调至3000-5000,bytes设为15-20MB(需确保ES线程池队列足够)。
若文档较大(如20-50KB):entries降至200-500,bytes设为5-10MB,避免单批过大。
总结
初期推荐es.batch.size.entries=1000,es.batch.size.bytes=10mb,根据实际运行情况(无拒绝、无超时)逐步上调,最终找到平衡吞吐量和稳定性的最佳值。核心是"小步测试,动态适配",避免一次性设置过大导致任务失败。
五、提升 es-hadoop hive更新es数据的效率
可以通过优化 ES-Hadoop 配置、Hive 数据处理、Elasticsearch 集群性能 三个维度提升从 Hive 更新 ES 数据的效率,具体方法如下:
一、优化 ES-Hadoop 写入参数
ES-Hadoop 提供了多个参数控制批量写入行为,合理调整可显著提升吞吐量:
1、增大批量写入规模(核心优化)
默认单次批量写入 1000 条文档(es.batch.size.entries=1000),可根据文档大小调整(如每条文档 1KB 时,可增至 5000-10000):
es.batch.size.entries=5000 # 单次批量写入 5000 条
es.batch.size.bytes=10mb # 单次批量大小不超过 10MB(避免请求过大超时)
注意:批量过大可能导致 ES 拒绝请求(es_rejected_execution_exception),需配合 ES 集群能力调整。
2、并行写入调优
控制 Hive/Spark 任务的并行度,使其与 ES 分片数匹配(并行度建议为分片数的 1-3 倍):
– Hive 中通过 map 数控制并行度(示例:设置 5 个 map)
set mapreduce.job.maps=5;
避免过度并行(如并行度远大于 ES 分片数),否则会导致 ES 写入线程池拥堵。
3、重试与超时配置
增加重试次数并延长超时时间,避免因瞬时压力导致任务失败重试:
es.batch.write.retry.count=5 # 重试 5 次
es.batch.write.retry.wait=10s # 重试间隔 10 秒
es.http.timeout=60s # HTTP 请求超时延长至 60 秒
二、优化 Hive 数据处理链路
1、减少数据传输量
过滤无效数据:在 Hive 中提前过滤不需要更新的字段或文档(如通过 where 条件筛选增量数据)
裁剪字段:只选择需要写入 ES 的字段,避免传输冗余数据
2、优化 Hive 任务性能
合并小文件:Hive 中过多小文件会导致 ES-Hadoop 产生大量小批量请求,可通过 INSERT OVERWRITE 合并:
SET hive.merge.mapfiles=true;
SET hive.merge.mapredfiles=true;
SET hive.merge.size.per.task=256000000; # 合并后文件大小 256MB
INSERT OVERWRITE TABLE hive_table SELECT * FROM hive_table;
使用 Tez 引擎:相比 MapReduce,Tez 引擎处理 Hive 任务效率更高:
set hive.execution.engine=tez;
三、优化 Elasticsearch 集群写入性能
ES 集群是写入瓶颈时,需从索引配置和集群资源两方面优化:
1、临时调整索引配置(写入期间)
关闭副本:写入时将副本数设为 0(减少数据同步开销),完成后恢复:
-- 写入前关闭副本
curl -XPUT "http://es-host:9200/group_tag_all_boci/_settings" -d '{"number_of_replicas": 0}'
-- 写入后恢复副本
curl -XPUT "http://es-host:9200/group_tag_all_boci/_settings" -d '{"number_of_replicas": 1}'
--延长刷新间隔:默认 1 秒刷新一次(生成可查询的 Segment),写入时延长至 30 秒:
curl -XPUT "http://es-host:9200/group_tag_all_boci/_settings" -d '{"refresh_interval": "30s"}'