我们知道全量替换的语法和文档创建语法一样.PUT /index/type/id{ field}
全量替换和文档创建在es中的操作:对写入的数据再内存中执行,创建一个新的doucument,然后将旧的标记为deleted。
所以你存入的原有数据有2个filed,但是当你进行全量替换的时候却只有1个filed,此时的document 对应只有1个field,而我们想要的结果是,只是针对某个字段进行修改。
这时,如果仍然要使用全量替换来进行数据修改步骤会相对多。
例如:此时有一个document如下
{
"price":200,
"productName":"apple",
"tag"::["fresh"]
},
需要修改price价格为100,
语法为:
{
"price":100,
"productName":"apple",
"tag"::["fresh"]
},·
为了进行一个字段修改,我们必须需要知道其他字段的值,这是我们就需要进行一次查询,查询该document的所有字段值,然后将不需要修改的字段原封不动写入到语句中,
也就是说,全量替换的操作步骤总结为:
1.进行一次get查询操作,查找需要进行修改的doucment对应所有详细信息。
2.除了需要修改的字段进行字段修改,其他数值原封不动的写入put请求中
可以很容易的看出,进行一次真正的数据的修改,需要用户先进行查询,然后对查询的数据进行修改之后在写入到es中,耗费的时间相对的也会更长。在写入的数据的时候,可能别人已经对数据进行了修改,容易产生并发冲突的情况
然后我们来看看partial update,从字面上来看,就可以看出来该方式是一个部分字段的修改。
其实partial update 的执行,和全量替换是一致的,都是先获取document数据,然后将传过来的filed更新到document的json中,将老的document标记为deleted,然后创建新的docuemnt,
但是相比较于全量替换,partial update 的所有查询修改都是在es内部执行的。操作基本都是毫秒级别的,花费的时间也就相对较少,发生并发冲突的可能性也就相对较小。
另外一个小知识点,由于partial update的查询和更新操作都是在es内部执行,es相关的乐观锁操作也是在es内部进行。乐观锁由于其需要进行version的比对,所以在高并发的情况下可能多次进行version对比。retry策略可以用来指定次数,例如5,此时partial update只会进行5次的查询更新操作尝试,要么成功修改,要么尝试5次还没有修改成功,就结束修改操作
语法格式:post /index/type/id/_update?retry_on_conflict=5&version=6
总结:
从而我们可以看出来,其实partial update 与全量替换的执行步骤是 一致的,但是partial update所有的查询和修改操作都是在es的某个shard中进行的,避免了网络数据传输的开销,大大提升性能。
第二是由于查询和修改是在es内部执行的,操作时间基本为毫秒级别,有效减少并发冲突。