首先来说一下为何会有partial update。
在以前对于建立文档和更新替换文档的格式都是:json
PUT /{index}/{type}/{id} {}
通常对应到应用程序中,每次的执行流程基本都是这样的:
(1)应用程序先发起一个get请求,获取到document,展现到前台界面,供用户查看和修改
(2)用户在前台界面修改数据,发送到后台
(3)后台代码会将用户修改的数据在内存中进行执行,而后封装好修改后的全量数据
(4)而后在发送PUT请求到ES中,进行全量替换
(5)ES会将老的document标记为deleted,而后从新建立一个新的document网络
以前的流程有1个问题就是每次修改数据的时候,因为都是替换,因此每次带上的字段不只包括要修改的字段,还须要带上其它的全部字段(即便那些字段根本就不须要修改)。
针对这一点,因而ES就有了partial update。格式就是:并发
POST /{index}/{type}/{id}/_update { "doc": { "须要修改的字段" } }
这样看起来好像是方便了不少,每次修改时只须要传入少数几个发生修改的字段便可,不须要将全量的document数据发送过去。性能
partial update实现原理:从本质上来讲,它的实现原理和传统的全量替换的方式是几乎同样的。
过程以下:
(1)在内部会先获取document
(2)将传过来的field更新到document的json中去
(3)将旧的document标记为deleted
(4)将修改后的新的document建立出来
既然说本质都同样,那它相比传统的方式优势在哪里呢?
比较以后不难发现有如下的优势:
(1)全部的查询、修改和写回操做都发生在ES中的一个shard内部,与传统全量替换将操做放在内存的方式相比,避免了全部网络数据传输的开销(减小了2次网络请求),大大提高了性能
(2)减小了查询和修改中的时间间隔,能够有效减小并发冲突的状况
实践:spa
PUT /test_index/_doc/3 { "test_field1": "test1", "test_field2": "test2" } GET /test_index/_doc/3 { "_index" : "test_index", "_type" : "_doc", "_id" : "3", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { "test_field1" : "test1", "test_field2" : "test2" } } POST /test_index/_update/3 { "doc": { "test_field2" : "update test2" } } GET /test_index/_doc/3 { "_index" : "test_index", "_type" : "_doc", "_id" : "3", "_version" : 2, "_seq_no" : 1, "_primary_term" : 1, "found" : true, "_source" : { "test_field1" : "test1", "test_field2" : "update test2" } }