在對text字段進行搜尋的時候,假如你需要對多個text類型的字段搜尋,例如 文章的标題和文章的内容,這兩個字段。
在這種情況下,是可以開啟copy_to來提速的。我測試的提速效果在百分之五十左右。
它是将這兩個字段copy到一個字段上,然後進行分詞處理。之是以會快,就是因為如果你多個字段,要做多次的查詢,如果合并到一個字段上,隻需要做一次查詢。
但是請注意,它會額外花費比較多的磁盤資源!
測試結論
對兩個text類型字段檢索,資料内容為文章和标題。開啟copy_to以後,搜尋提升百分之五十左右。磁盤額外占用百分之二十五左右。
如何開啟copy_to
我這裡不做過多的介紹了,直接看官網吧。
copy_to | Elasticsearch Guide [8.4] | Elastic
看看資源花費情況
GET _cat/indices?v
可以看到索引在開啟copy_to前是583G,開啟後是724G。磁盤多花費了24%。這個要根據自己資料情況,具體去測試分析。因為大家的資料,場景都不一樣。

看看提升效果
我是寫測試程式跑了幾百個搜尋詞條件,做測試。搜尋就是query_string,然後mache_phrase
測試代碼如下:
@Override
public void comparisonCopyTo() throws IOException {
// 搜尋詞
List<String> queryList = Arrays.asList("中國", "美國", "疫情", "蘋果", "華為", "利好", "浪漫", "馬斯特",
"特斯拉", "台灣", "香港", "美食", "微信", "晴天", "北京", "救援", "失敗", "報警",
"媒體", "新疆", "京東", "深圳", "爆炸", "事故", "征地", "抗議", "聚衆",
"堵路", "打砸", "罷工", "跳樓", "招募", "黑旅館", "争議", "盜竊", "碰車",
"不滿", "黑中介", "失火", "舉報", "公道", "經濟學家", "中國新聞周刊", "永定河", "中國大地财産保險股份有限公司", "冬奧",
"天津大事件");
// 對比邏輯:相同的搜尋詞,去對比搜尋時間,列印日志,校驗搜尋結果
for (String queryString:queryList) {
HashMap<String, Float> fields = new HashMap<>();
fields.put("content", 1.0F);
fields.put("title", 1.0F);
QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(queryString).fields(fields).type(MultiMatchQueryBuilder.Type.PHRASE);
SearchResponse data = commonsDao.basicSearch(queryBuilder, 10, true, "all_data");
// 查詢copy-to的字段
HashMap<String, Float> copyToFields = new HashMap<>();
copyToFields.put("full_search", 1.0F);
QueryStringQueryBuilder copyToQueryBuilder = QueryBuilders.queryStringQuery(queryString).fields(copyToFields).type(MultiMatchQueryBuilder.Type.PHRASE);
SearchResponse copyToData = commonsDao.basicSearch(copyToQueryBuilder, 10, true, "all_data_copy_to");
log.info("copy-to測試對比(un copy-to vs copy-to), 搜尋詞 {},查詢時間對比 {} vs {}, 查詢性能提升 {}% ,查詢結果對比 {} vs {}", queryString,
data.getTook().getMillis(), copyToData.getTook().getMillis(), (float)(data.getTook().getMillis() - copyToData.getTook().getMillis())/data.getTook().getMillis()*100,
data.getHits().getTotalHits().value, copyToData.getHits().getTotalHits().value);
}
}