Elasticsearch刪除數據之_delete_by_query


es參考版本:elasticsearch:5.5
_delete_by_query會刪除所有query語句匹配上的文檔,用法如下:

curl -X POST "localhost:9200/twitter/_delete_by_query" -H 'Content-Type: application/json' -d' { "query": { "match": { "name": "測試刪除" } } } ' 

查詢必須是有效的鍵值對,query是鍵,這和Search API是同樣的方式。在search apiq參數和上面效果是一樣的。

返回數據格式,告訴你用時和刪除多少數據等

{
  "took" : 147, "timed_out": false, "deleted": 119, "batches": 1, "version_conflicts": 0, "noops": 0, "retries": { "bulk": 0, "search": 0 }, "throttled_millis": 0, "requests_per_second": -1.0, "throttled_until_millis": 0, "total": 119, "failures" : [ ] } 

當啟動時(開始要刪除時),_delete_by_query會得到索引(數據庫)的快照並且使用內部版本號來找到要刪除哪些文檔。這意味着,如果獲取到快照與執行刪除過程的這段時間,有文檔發生改變,那么版本就會沖突。通過版本控制匹配到的文檔會被刪除。

因為internal版本控制不支持0為有效數字,所以版本號為0的文檔不能刪除,並且請求將會失敗。

在執行_delete_by_query期間,為了刪除匹配到的所有文檔,多個搜索請求是按順序執行的。每次找到一批文檔時,將會執行相應的批處理請求來刪除找到的全部文檔。如果搜索或者批處理請求被拒絕,_delete_by_query根據默認策略對被拒絕的請求進行重試(最多10次)。達到最大重試次數后,會造成_delete_by_query請求中止,並且會在failures字段中響應 所有的故障。已經刪除的仍會執行。換句話說,該過程沒有回滾,只有中斷。
在第一個請求失敗引起中斷,失敗的批處理請求的所有故障信息都會記錄在failures元素中;並返回回去。因此,會有不少失敗的請求。
如果你想計算有多少個版本沖突,而不是中止,可以在URL中設置為conflicts=proceed或者在請求體中設置"conflicts": "proceed"。

回到api格式中,你可以在一個單一的類型(即:表)中限制_delete_by_query。
下面僅僅只是刪除索引(即:數據庫)twitter中類型(即:表)tweet的所有數據:

curl -X POST "localhost:9200/twitter/_doc/_delete_by_query?conflicts=proceed" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} } } ' 

一次刪除多個索引(即:數據庫)中的多個類型(即表)中的數據,也是可以的。例如:

curl -X POST "localhost:9200/twitter,blog/_docs,post/_delete_by_query" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} } } ' 

如果你提供了routing,接着這個路由會被復制給scroll query,根據匹配到的路由值,來決定哪個分片來處理:

curl -X POST "localhost:9200/twitter/_delete_by_query?routing=1" -H 'Content-Type: application/json' -d' { "query": { "range" : { "age" : { "gte" : 10 } } } } ' 

默認情況下,_delete_by_query自上而下批量1000條數據,你也可以在URL中使用參數scroll_size:

curl -X POST "localhost:9200/twitter/_delete_by_query?scroll_size=5000" -H 'Content-Type: application/json' -d' { "query": { "term": { "user": "kimchy" } } } ' 

URL Parameters(url 參數)

除了標准參數像prettyDelete By Query API也支持refreshwait_for_completionwait_for_active_shardstimeout

發送帶refresh參數的請求一旦完成,在delete by queryapi中涉及到的所有分片都將會刷新。這不同於Delete API中的refresh參數,其是在收到刪除請求時就刷新分片。

如果請求中包含wait_for_completion=false,那么elasticsearch將會執行預檢查啟動請求,並返回一個可被Tasks APIs使用的task,以取消或者得到task狀態。elasticsearch也將會在.tasks/task/${taskId}路徑中創建一個文檔來記錄這個task。你可以根據自己的情況來選擇保留還是刪除它;當你刪除后,elasticsearch會回收利用它的空間。

在處理請求之前,wait_for_active_shards控制需要多少個副本分片必須處於活動狀態。詳情這里timeout用於控制每個寫請求等待不可用分片變成可用分片的時間。兩者都能在Bulk API中正常工作。

requests_per_second可以設置任何正的十進制數字(1.4、6、1000等等)並且可以限制delete-by-query發出的每秒請求數量或者將其設置為-1來禁用這種限制。這種限制會在批處理之間等待,以便於其能操作scroll timeout。這個等待時間與完成批處理之間的時間和requests_per_second * requests_in_the_batch時間是有區別的。由於批處理不會分解成多個請求,而如此大的批處理將會造成elasticsearch創建多個請求並且會在開始下個集合(批處理)之前等待一會,這是bursty而不是smooth。默認為-1

Response body(響應體)

響應體的json格式如下:

{
  "took" : 639, "deleted": 0, "batches": 1, "version_conflicts": 2, "retries": 0, "throttled_millis": 0, "failures" : [ ] } 

參數 描述
took 從整個操作開始到結束花費的時間,單位是毫秒
deleted 成功刪除文檔的數量
batches 通過delete by query返回滾動響應的數量(我的看法:符合delete by query條件的文檔數量)
version_conflicts delete by queryapi命中的沖突版本的數量(即在執行過程中,發生了多少次沖突)
retries 在delete by query api響應一個完整隊列,重試的次數
throttled_millis 根據requests_per_second,請求睡眠多少毫秒
failures 是個數組,表示失敗的所有索引(插入);如果它不為空的話,那么請求會因為故障而中止。可以參考如何防止版本沖突而中止操作。

Works with the Task API

你可以使用Task API來獲取任何一個正在運行的delete-by-query請求的狀態。

curl -X GET "localhost:9200/_tasks?detailed=true&actions=*/delete/byquery" 

響應

{
  "nodes" : { "r1A2WoRbTwKZ516z6NEs5A" : { "name" : "r1A2WoR", "transport_address" : "127.0.0.1:9300", "host" : "127.0.0.1", "ip" : "127.0.0.1:9300", "attributes" : { "testattr" : "test", "portsfile" : "true" }, "tasks" : { "r1A2WoRbTwKZ516z6NEs5A:36619" : { "node" : "r1A2WoRbTwKZ516z6NEs5A", "id" : 36619, "type" : "transport", "action" : "indices:data/write/delete/byquery", "status" : { [](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html#CO38-1)![](//upload-images.jianshu.io/upload_images/4097351-8117f89c35e1e6d2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) "total" : 6154, "updated" : 0, "created" : 0, "deleted" : 3500, "batches" : 36, "version_conflicts" : 0, "noops" : 0, "retries": 0, "throttled_millis": 0 }, "description" : "" } } } } }</pre> 

①這個對象包含實際的狀態。響應體是json格式,其中total字段是非常重要的。total表示期望執行reindex操作的數量。你可以通過加入的updated、created和deleted字段來預估進度。但它們之和等於total字段時,請求將結束。

使用task id可以直接查找此task。

curl -X GET "localhost:9200/_tasks/taskId:1" 

這個api的優點是它整合了wait_for_completion=false來透明的返回已完成任務的狀態。如果此任務完成並且設置為wait_for_completion=false,那么其將返回results或者error字段。這個特性的代價就是當設置wait_for_completion=false時,會在.tasks/task/${taskId}中創建一個文檔。當然你也可以刪除這個文檔。

curl -X POST "localhost:9200/_tasks/task_id:1/_cancel" 

可以使用上面的task api來找到task_id;
取消應該盡快發生,但是也可能需要幾秒鍾,上面的task 狀態 api將會進行列出task直到它被喚醒並取消自己。

curl -X POST "localhost:9200/_delete_by_query/task_id:1/_rethrottle?requests_per_second=-1" 

Rethrottling

requests_per_second的值可以在使用_rethrottle參數的正在運行的delete by queryapi上進行更改:

curl -X POST "localhost:9200/_delete_by_query/task_id:1/_rethrottle?requests_per_second=-1" 

使用上面的tasks API來查找task_id

就像在_delete_by_query中設置一樣,requests_per_second可以設置-1來禁止這種限制或者任何一個10進制數字,像1.7或者12來限制到這種級別。加速查詢的Rethrottling會立即生效,但是緩慢查詢的Rethrottling將會在完成當前批處理后生效。這是為了防止scroll timeouts。

Manually slicing

Delete-by-query支持Sliced Scroll,其可以使你相對容易的手動並行化進程:

curl -X POST "localhost:9200/twitter/_delete_by_query" -H 'Content-Type: application/json' -d' { "slice": { "id": 0, "max": 2 }, "query": { "range": { "likes": { "lt": 10 } } } } ' curl -X POST "localhost:9200/twitter/_delete_by_query" -H 'Content-Type: application/json' -d' { "slice": { "id": 1, "max": 2 }, "query": { "range": { "likes": { "lt": 10 } } } } ' 

你可以通過以下方式進行驗證:

curl -X GET "localhost:9200/_refresh" curl -X POST "localhost:9200/twitter/_search?size=0&filter_path=hits.total" -H 'Content-Type: application/json' -d' { "query": { "range": { "likes": { "lt": 10 } } } } ' 

像下面這樣只有一個total是合理的:

{
  "hits": { "total": 0 } } 

Automatic slicing

你也可以使用Sliced Scroll讓delete-by-query api自動並行化,以在_uid上切片:

curl -X POST "localhost:9200/twitter/_delete_by_query?refresh&slices=5" -H 'Content-Type: application/json' -d' { "query": { "range": { "likes": { "lt": 10 } } } } ' 

你可以通過以下來驗證:

curl -X POST "localhost:9200/twitter/_search?size=0&filter_path=hits.total" -H 'Content-Type: application/json' -d' { "query": { "range": { "likes": { "lt": 10 } } } } ' 

像下面的total是一個合理的結果:

{
  "hits": { "total": 0 } } 

添加slices_delete_by_query將會自動執行上面部分中使用手動處理的部分,創建子請求這意味着有些怪事:

  1. 你可以在Tasks APIs中看到這些請求。這些子請求是使用了slices請求任務的子任務。
  2. 為此請求(使用了slices)獲取任務狀態僅僅包含已完成切片的狀態。
  3. 這些子請求都是獨立尋址的,例如:取消和rethrottling.
  4. Rethrottling the request with slices will rethrottle the unfinished sub-request proportionally.
  5. 取消slices請求將會取消每個子請求。
  6. 由於slices的性質,每個子請求並不會得到完全均勻的文檔結果。所有的文檔都將要處理,但是有些slices(切片)會大些,有些會小些。希望大的slices(切片)有更均勻的分配。
  7. slices請求中像requests_per_secondsize參數,按比例分配給每個子請求。結合上面的關於分配的不均勻性,你應該得出結論:在包含slices_delete_by_query請求中使用size參數可能不會得到正確大小的文檔結果。
  8. 每個子請求都會獲得一個略微不同的源索引快照,盡管這些請求都是大致相同的時間。

Picking the number of slices

這里我們有些關於slices數量的建議(如果是手動並行的話,那么在slice api就是max參數):

  1. 不要使用大數字。比如500,將會創建相當大規模的CPU震盪。
    這里說明下震盪(thrashing)的意思:
    cpu大部分時間都在進行換頁,而真正工作時間卻很短的現象稱之為thrashing (震盪)
  2. 從查詢性能角度來看,在源索引中使用多個分片是更高效的。
  3. 從查詢性能角度來看,在源索引中使用和分片相同的數量是更高效的。
  4. 索引性能應該在可利用slices之間進行線性擴展。
  5. 索引(插入)或查詢性能是否占主導地位取決於諸多因素,比如:重新索引文檔和集群進行重新索引。

參考:

https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
https://blog.csdn.net/u013066244/article/details/76258188





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM