一、需求
當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