Elasticsearch中_update_by_query复制字段过慢,如何提速?
问题描述
我正在使用Painless脚本和_update_by_query操作,将Elasticsearch中object类型字段的数据复制到nested类型字段中。集群处理840万条数据耗时约48小时,希望能加快该操作速度。使用的请求如下:
请求URL:
localhost:9200/myindex/_update_by_query?conflicts=proceed&requests_per_second=50
请求体:
{ "query": { "match_all": {} }, "script": { "inline": "ctx._source.myfield_copy = ctx._source.myfield;" } }
加速操作的优化方案
- 移除请求速率限制:当前设置的
requests_per_second=50会强制限制每秒处理的请求数,直接删除这个参数,让Elasticsearch根据集群硬件资源全力推进任务。 - 启用并行分片处理:
- 使用
slice参数拆分任务为多个并行子任务,比如在URL中添加slice=auto,让Elasticsearch自动按索引分片数拆分任务;也可以手动指定分片,比如同时发起多个请求:localhost:9200/myindex/_update_by_query?conflicts=proceed&slice=0&max_slice=4、slice=1&max_slice=4等,并行处理不同分片的文档。 - 增大
scroll_size参数(默认1000),比如设置为scroll_size=2000(根据集群内存调整,不要超过JVM堆内存的10%),单次拉取更多文档批量处理,减少请求往返次数。
- 使用
- 优化脚本执行效率:
- 将inline脚本改为存储脚本,避免每次请求重复解析脚本。先创建存储脚本:
后续请求体中直接引用存储脚本ID:PUT _scripts/copy_field_script { "script": { "lang": "painless", "source": "ctx._source.myfield_copy = ctx._source.myfield;" } }{ "query": {"match_all": {}}, "script": {"id": "copy_field_script"} }
- 将inline脚本改为存储脚本,避免每次请求重复解析脚本。先创建存储脚本:
- 临时降低写入开销:
- 临时将索引副本数设为0:
PUT /myindex/_settings {"number_of_replicas": 0},操作完成后再恢复原副本数,避免同步副本的写入耗时。 - 临时关闭索引自动刷新:
PUT /myindex/_settings {"index.refresh_interval": "-1"},任务完成后恢复默认刷新间隔(如30s),减少频繁刷新带来的IO消耗。
- 临时将索引副本数设为0:
- 缩小处理范围(若可行):如果不是所有文档都需要更新,修改
query条件只匹配目标文档,减少需要处理的总数据量,避免无意义的遍历。 - 选择低负载时段执行:在业务流量低谷期启动任务,避免和线上业务争抢CPU、内存、IO资源。
内容的提问来源于stack exchange,提问作者sainivetha
相关产品推荐
相关产品推荐

