首先來說一下爲何會有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" } }