Elasticsearch写入数据原理
是的发送到
- 客户端发起写入请求
- 写入内存缓存区,并写入数据到translog buffer
- 每隔1s数据从buffer中refresh到FileSystemCache中,生成segment文件,一旦生成segment文件,就能通过索引查询到了;
- refresh完,memory buffer就清空了;
- 每隔5s中,translog 从buffer flush到磁盘中;
- 定期/定量从FileSystemCache中,结合translog内容flush index到磁盘中。做增量flush的。
ES的近实时查询主要是因为从内存缓存区生成segment之间的延迟。
插入数据性能测试
Es提供了三种刷新策略
- 插入即刷新
- wait_for 1秒后刷新 时间可设置
- 不执行刷新相关操作。此请求所做的更改将在请求返回后的某个时刻可见。
通过代码验证一下这三种策略
从数据库读取5000条数据,分别用不同的策略插入到ES中,查看响应的耗时
关键代码如下:
IndexResponse response = esClient.index(i-> i.index(index)
.id((String.valueOf(resident.getId()))).
document(resident).refresh(Refresh.True));
结论
立即刷新 耗时:545064毫秒
不刷新 耗时: 24583毫秒
wait_for 耗时 5473795毫秒
使用wait_for 比立即刷新还耗时,难以理解,希望有知道的大佬,可以指点一下
测试环境是在docke4.27.2 Elasticsearch 8.6.2
基于wait_for更耗时这里做一下说明
通过验证发现,插入每条数据,耗时差不多都是1秒多点儿。
2024-06-28 10:07:30.868 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1043
2024-06-28 10:07:31.936 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1044
2024-06-28 10:07:33.051 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1045
2024-06-28 10:07:34.155 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1046
2024-06-28 10:07:35.267 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1047
2024-06-28 10:07:36.367 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1048
2024-06-28 10:07:37.485 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1049
2024-06-28 10:07:38.611 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1050
2024-06-28 10:07:39.717 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1051
2024-06-28 10:07:40.832 INFO 22152 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1052
1秒是个敏感词,会不会跟默认的刷新频率有关呢?
做以下验证
- 修改默认刷新频率
put /resident/_settings
{
"index" : {
"refresh_interval" : "2s"
}
}
- 再做验证
2024-06-28 10:11:56.296 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1043
2024-06-28 10:11:58.364 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1044
2024-06-28 10:12:00.489 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1045
2024-06-28 10:12:02.611 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1046
2024-06-28 10:12:04.707 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1047
2024-06-28 10:12:06.814 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1048
2024-06-28 10:12:08.913 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1049
2024-06-28 10:12:11.012 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1050
2024-06-28 10:12:13.115 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1051
2024-06-28 10:12:15.228 INFO 23376 --- [ main] com.itcv.service.impl.EsServiceImpl : 向ES中添加数据,数据已存在进行修改1052
耗时变成了两秒多
批量添加数据
public boolean batchAddData(String index, List<Resident> residentList){
try {
BulkRequest.Builder br = new BulkRequest.Builder();
for (Resident r : residentList){
br.operations(op ->
op.index(idx ->
idx.index("resident")
.id(String.valueOf(r.getId()))
.document(r)
)
).refresh(Refresh.WaitFor);
}
BulkResponse result = esClient.bulk(br.build());
log.info(JSONObject.toJSONString(result));
} catch (Exception e) {
log.error("向ES中添加数据失败",e);
}
return false;
}
一次性批量写入5000条数据耗时 2435毫秒,批量写入性能是最高的
参考文章
https://longxiaofei.github.io/post/elasticsearch%E7%9A%84%E5%86%99%E5%85%A5%E6%B5%81%E7%A8%8B/
https://blog.csdn.net/weixin_42586723/article/details/120441348