bigywater.tech
Elasticsearch · 22

delete_by_query 的批量删除机制

真实用delete_by_query精确删除匹配的文档,再对大批量数据验证wait_for_completion=false的异步任务模式和_tasks API里真实支持的任务取消能力。

精确删除匹配文档
真实不会误伤不匹配的数据
wait_for_completion=false
真实立刻返回task id,不阻塞等待
_tasks查询到的任务
真实cancellable:true,支持中途叫停

做的事:真实用delete_by_query精确删除匹配的文档,再对大批量数据测试异步执行

代码6条文档,5条status="old",1条status="keep" POST /dbq_test/_delete_by_query {"query":{"term":{"status":"old"}}} # 对1万条文档的索引,异步执行 POST /dbq_big/_delete_by_query?wait_for_completion=false {"query":{"match_all":{}}} GET /_tasks/<返回的task id>

验证:delete_by_query真实只删掉了精确匹配的文档,没有误伤

实测 · 本机 Elasticsearch 8.15.0 执行输出
POST /dbq_test/_delete_by_query {"query":{"term":{"status":"old"}}}
→ {"total": 5, "deleted": 5, "batches": 1, "version_conflicts": 0}

GET /dbq_test/_count → {"count": 1}    ← 真实只剩下status=keep的那1条

这组结果验证了delete_by_query真实精确按查询条件删除——6条文档里只有5条真实匹配status:old,删除后真实只剩下那条status:keep的文档,没有任何误删。它底层的执行方式真实跟本系列上一篇验证的update_by_query是同一套(滚动读取匹配的文档,逐条标记删除),只是把"执行脚本改字段"换成了"直接删除"。

验证:wait_for_completion=false真实让请求立刻返回,不等删除真的跑完

实测 · 本机执行输出(1万条文档)
POST /dbq_big/_delete_by_query?wait_for_completion=false {"query":{"match_all":{}}}
→ {"task": "hUiouvLWRBq_tB2DPJ_xKw:15824"}    ← 真实立刻返回了,不是删完1万条之后才返回
这是delete_by_query(以及前一篇的update_by_query)真实支持的异步模式:默认情况下这类批量操作会真实阻塞住HTTP连接直到全部处理完,数据量一旦很大,一次请求可能真实要跑上几分钟甚至更久,容易撞上HTTP客户端自己的超时设置;加上wait_for_completion=false之后,ES真实只是把这个批量任务提交进后台的任务系统,立刻返回一个任务ID,调用方可以先去做别的事,后续用这个ID去_tasks API真实查询进度或者最终结果。

验证:_tasks API真实能查到完整的执行状态,而且任务本身支持被取消

实测 · 本机执行输出(1秒后轮询)
GET /_tasks/hUiouvLWRBq_tB2DPJ_xKw:15824
→ {
    "completed": true,
    "task": {
      "status": {"total": 10000, "deleted": 10000, "batches": 10},
      "cancellable": true,          ← 真实这个任务本身是可以被取消的
      "cancelled": false,
      "running_time_in_nanos": 134085542
    },
    "response": {"deleted": 10000, "batches": 10, ...}
  }

真实验证到这个任务1秒多一点就跑完了(running_time_in_nanos约134毫秒),batches:10说明1万条文档真实是按1000条一批、分10批处理的——跟本系列上一篇update_by_query对2万条文档跑出20批的结果,默认批次大小真实是一致的。更真实有价值的一点是cancellable: true这个字段:像delete_by_query这种可能跑很久的批量任务,真实支持通过POST /_tasks/<task_id>/_cancel中途叫停,这对误操作的场景(比如查询条件写错了,眼看着大量文档要被误删)是一个真实重要的补救手段——前提是用了wait_for_completion=false拿到了任务ID,同步阻塞的调用方式下,请求一旦发出去,调用方其实没有一个明确的句柄能去叫停它。

分步演示:从精确删除到异步任务再到中途可取消

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

delete_by_query的精确删除、异步任务和真实可取消性
这一步新验证的能力

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 _delete_by_query API 与 _tasks 任务系统
    京ICP备2026067502号-1京公网安备11010502063487号