一、需求
当es字段类型无法支撑业务需求,需要修改到字段类型的时候。例如修改字段类型从Integer变成double,这种情况下,是没办法修改es的字段的type的。
原因是一个字段的类型进行修改之后,ES会重新建立对这个字段的索引信息,ElasticsSearch的底层是Lucene库,字段类型修改会涉及到分词方式,相关度,TF/IDF等倒排的生成 , 所以是没办法修改的了。
这种情况下,如何能兼容旧数据的同时,实现修改字段类型?
二、如何实现:es的reindex
实现原理:通过es的reindex功能把旧索引的数据reindex到新索引,然后为新索引建立旧索引的别名,最后删除旧索引。
下面以重构:idt-shelf-2265-index-202003 下的 shelf_sub_job 中的Integer字段变为double为例子
- 新建一个索引:idt-shelf-2265-index-202003-temp (注:该索引下的数据表type和原索引保持一致。其中,新索引中的字段属性已修改为double)
*可通过EsIndexService类创建一个新的索引。 - 执行reindex操作,把旧索引的数据复制到新索引:
POST _reindex
{
"source": {
"index": "idt-shelf-2265-index-202003"
},
"dest": {
"index": "idt-shelf-2265-index-202003-temp"
}
}
-
执行该操作后,可以在kibana上面查看进度:
- 删除旧索引:
DELETE idt-shelf-2265-index-202003
修改新索引的别名为“idt-shelf-2265-index-202003”:
POST /_aliases
{
"actions": [
{"add": {"index": "idt-shelf-2265-index-202003-temp", "alias":idt-shelf-2265-index-202003"}}
]
}
三、查询reIndex进度、终止reIndex
查询reIndex进度
GET _tasks?detailed=true&actions=*reindex
取消reIndex任务
POST _tasks/node_id:task_id/_cancel
四、提升reIndex速度
从第二步能看出,reindex速度非常慢,每秒只有200条数据。
提升reindex的几个点:
(1)修改批量大小值
默认情况下,_reindex使用1000进行批量操作,您可以在source中调整batch_size
POST _reindex
{
"source": {
"index": "source",
"size": 5000
},
"dest": {
"index": "dest",
"routing": "=cat"
}
}
(2)ES副本数设置为0
我们看下一个文档被创建的流程:
一个创建请求,在主分片创建了文档后,会转发请求到副本所在到节点,待副本创建成功后,才返回给客户端。
所以在reindx的时候,提升速度,可以考虑把副本数设置为0,待reindex成功后,再设置为1,es会自动建立副本。
PUT /idt-shelf-2265-index-202003-temp/_settings
{
"number_of_replicas": 0
}
如下效果,副本数设置为0后,主分片的速率得到了很大的提升。
(reindex完毕后,要记得设置副本数~)
(3)修改Refresh的间隔时间
如果你的搜索结果不需要近实时的准确度,考虑把每个索引的 index.refresh_interval改到 30s 。如果你是在做大批量导入,导入期间你可以通过设置这个值为 -1 关掉刷新。别忘记在完工的时候重新开启它。
PUT /idt-shelf-2265-index-202003-temp/_settings
{
"refresh_interval": -1
}
如下效果图,我把刷新时间设置为120s比30s效果要好,但设置为关闭刷新,反而效果变差了??
五、安全考虑
1、进行以上操作的时候,建议先对索引建立快照备份。
2、reindex操作前考虑清楚,一来太耗时了,二来reindex过程中,原索引新增的数据,是没有被reindex过去,看看reindex的原理就是明白,用的是scroller
附:es索引性能优化技巧文档
https://www.elastic.co/guide/cn/elasticsearch/guide/current/indexing-performance.html