天天看點

elasticsearch之Document APIs【Delete By Query API】環境Delete By Query APIURL Parameters(url 參數)Response body(響應體)Works with the Task APIWorks with the Cancel Task APIRethrottlingManually slicingAutomatic slicingPicking the number of slices

環境

虛拟機:centos7

作業系統:win7

elasticsearch:5.5

Delete By Query API

_delete_by_query 的簡單用法,就是在查詢比對到的每個文檔上執行删除。例如:

POST twitter/_delete_by_query
{
  "query": { ①
    "match": {
      "message": "some message"
    }
  }
}
           

①:查詢必須是有效的鍵值對,

query

是鍵,這和

Search API

是同樣的方式。在

search api

q

參數和上面效果是一樣的。

結果:

{
  "took" : ,
  "timed_out": false,
  "deleted": ,
  "batches": ,
  "version_conflicts": ,
  "noops": ,
  "retries": {
    "bulk": ,
    "search": 
  },
  "throttled_millis": ,
  "requests_per_second": -,
  "throttled_until_millis": ,
  "total": ,
  "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

的所有資料:

POST twitter/tweet/_delete_by_query?conflicts=proceed
{
  "query": {
    "match_all": {}
  }
}
           

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

POST twitter,blog/tweet,post/_delete_by_query
{
  "query": {
    "match_all": {}
  }
}
           

如果你提供了

routing

,接着這個路由會被複制給

scroll query

,根據比對到的路由值,來決定哪個分片來處理:

POST twitter/_delete_by_query?routing=
{
  "query": {
    "range" : {
        "age" : {
           "gte" : 
        }
    }
  }
}
           

預設情況下,

_delete_by_query

自上而下批量1000條資料,你也可以在URL中使用參數

scroll_size

POST twitter/_delete_by_query?scroll_size=
{
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
           

URL Parameters(url 參數)

除了标準參數像

pretty

Delete By Query API

也支援

refresh

wait_for_completion

wait_for_active_shards

timeout

發送帶

refresh

參數的請求一旦完成,在

delete by query

api中涉及到的所有分片都将會重新整理。這不同于

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" : ,
  "deleted": ,
  "batches": ,
  "version_conflicts": ,
  "retries": ,
  "throttled_millis": ,
  "failures" : [ ]
}
           
參數 描述
took 從整個操作開始到結束花費的時間,機關是毫秒
deleted 成功删除文檔的數量
batches 通過

delete by query

返復原動響應的數量(我的看法:符合

delete by query

條件的文檔數量)
version_conflicts

delete by query

api命中的沖突版本的數量(即在執行過程中,發生了多少次沖突)
retries

delete by query api

響應一個完整隊列,重試的次數
throttled_millis 根據

requests_per_second

,請求睡眠多少毫秒
failures 是個數組,表示失敗的所有索引(插入);如果它不為空的話,那麼請求會因為故障而中止。可以參考如何防止版本沖突而中止操作。

Works with the Task API

你可以使用

Task API

來擷取任何一個正在運作的

delete-by-query

請求的狀态。

GET _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" : ,
          "type" : "transport",
          "action" : "indices:data/write/delete/byquery",
          "status" : {    ①
            "total" : ,
            "updated" : ,
            "created" : ,
            "deleted" : ,
            "batches" : ,
            "version_conflicts" : ,
            "noops" : ,
            "retries": ,
            "throttled_millis": 
          },
          "description" : ""
        }
      }
    }
  }
}
           

①這個對象包含實際的狀态。響應體是

json

格式,其中

total

字段是非常重要的。

total

表示期望執行

reindex

操作的數量。你可以通過加入的

updated

created

deleted

字段來預估進度。但它們之和等于

total

字段時,請求将結束。

使用

task id

可以直接查找此

task

GET /_tasks/taskId:
           

這個

api

的優點是它整合了

wait_for_completion=false

來透明的傳回已完成任務的狀态。如果此任務完成并且設定為

wait_for_completion=false

,那麼其将傳回

results

或者

error

字段。這個特性的代價就是當設定

wait_for_completion=false

時,會在

.tasks/task/${taskId}

中建立一個文檔。當然你也可以删除這個文檔。

Works with the Cancel Task API

任何一個

Delete By Query

都可以使用

Task Cancel API

來取消掉:

POST _tasks/task_id:1/_cancel
           

可以使用上面的

task api

來找到

task_id

取消應該盡快發生,但是也可能需要幾秒鐘,上面的

task 狀态 api

将會進行列出

task

直到它被喚醒并取消自己。

Rethrottling

requests_per_second

的值可以在使用

_rethrottle

參數的正在運作的

delete by query

api上進行更改:

使用上面的

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

,其可以使你相對容易的手動并行化程序:

POST twitter/_delete_by_query
{
  "slice": {
    "id": ,
    "max": 
  },
  "query": {
    "range": {
      "likes": {
        "lt": 
      }
    }
  }
}
POST twitter/_delete_by_query
{
  "slice": {
    "id": ,
    "max": 
  },
  "query": {
    "range": {
      "likes": {
        "lt": 
      }
    }
  }
}
           

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

GET _refresh
POST twitter/_search?size=&filter_path=hits.total
{
  "query": {
    "range": {
      "likes": {
        "lt": 
      }
    }
  }
}
           

像下面這樣隻有一個

total

是合理的:

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

Automatic slicing

你也可以使用

Sliced Scroll

delete-by-query api

自動并行化,以在

_uid

上切片:

POST twitter/_delete_by_query?refresh&slices=
{
  "query": {
    "range": {
      "likes": {
        "lt": 
      }
    }
  }
}
           

你可以通過以下來驗證:

POST twitter/_search?size=&filter_path=hits.total
{
  "query": {
    "range": {
      "likes": {
        "lt": 
      }
    }
  }
}
           

像下面的

total

是一個合理的結果:

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

添加

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_second

    size

    參數,按比例配置設定給每個子請求。結合上面的關于配置設定的不均勻性,你應該得出結論:在包含

    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

繼續閱讀