首页/数据/NoSQL 速查/_bulk 批量写入
Elasticsearch89 条

_bulk 批量写入

批量接口用 NDJSON 组织操作:动作行与文档行交替,支持 index/create/update/delete 四类动作;单条失败不影响其他条目,需逐条检查响应。

NoSQL 速查数据更新于 2026-10-13

_bulk 是什么

_bulk 是 Elasticsearch 的批量写入接口:请求体用 NDJSON 组织,动作行与文档行交替出现,支持 index、create、update、delete 四类动作。单条失败不会中断其余条目,因此响应必须逐条检查,只看 HTTP 状态码会漏掉失败项。它是日志采集与批量导入的主力接口,也是往索引写大量文档时最省往返开销的方式。

基本信息

格式每行一个 JSON,动作行加文档行成对出现,最后必须有换行
动作index(覆盖)、create(已存在则冲突)、update、delete
常用参数?refresh=wait_for 等待可见,routing 可指定分片
响应字段took、errors、items 数组,逐条含 status 与 result
适用版本Elasticsearch 7.x / 8.x
批量大小按几 MB 控制,几百到几千条一批

典型使用场景

  • 日志采集链路批量落库,减少请求往返
  • 数据迁移与重建:把源索引数据写进新索引
  • 批量补写字段或纠正文档内容
  • 初始化测试数据,一次灌入数千条
  • 跨系统同步:外部数据变更后批量写入搜索库
  • 批量删除历史数据,按 ID 集合一次提交

示例

示例
POST /_bulk?refresh=wait_for
{ "index": { "_index": "my-index", "_id": "1" } }
{ "title": "a" }
{ "create": { "_index": "my-index", "_id": "2" } }
{ "title": "b" }
{ "update": { "_index": "my-index", "_id": "3" } }
{ "doc": { "title": "c" } }
{ "delete": { "_index": "my-index", "_id": "4" } }
# 注意最后一行也要以换行符结尾,否则解析失败

响应逐层读法

字段含义关注点
took整体耗时(毫秒)结合批量大小评估吞吐
errors是否存在失败项为 true 必须逐条排查
items[].status单条 HTTP 状态200/201 成功、409 冲突、400 参数错
items[].result写入结果created / updated / deleted / noop
items[].error失败原因类型冲突与版本冲突最常见
items[]._id对应文档 ID用于回到原始批次定位

批量实践要点

  • 按体积切批,几 MB 一批比固定条数更稳
  • 导入期间把 refresh_interval 调大或设为 -1 提升吞吐
  • create 动作适合只允许插入一次的场景,冲突时返回 409
  • update 动作默认是部分更新,文档不存在可配 doc_as_upsert
  • 删除用 delete 动作比先查再删更省事
  • 解析 items 数组时按序号与本地批次对齐,才能定位失败文档

批量失败排查顺序

  • 先看响应里 errors 是否为 true
  • 过滤 items 里 status 非 2xx 的条目,读 error 的 type 与 reason
  • 类型冲突(mapper_parsing_exception)先核对字段映射
  • 版本冲突(version_conflict)确认是否并发更新同一文档
  • 被拒绝(es_rejected_execution)说明写入队列满,需要限速重试
  • 核对成功条数与源数据条数,差值必须补写
响应中 errors 为 true 时要逐条看 items[].error,常见原因是类型冲突与版本冲突,不能只看到 HTTP 200 就认为全部成功。
最后一行缺换行会导致解析失败,脚本拼 NDJSON 时注意补尾换行;动作行与文档行必须成对,delete 动作没有文档行。
单批体积过大会超时或被拒绝,按几 MB 切批;导入完成后恢复 refresh_interval 并手动 refresh 一次。
被拒绝的错误通常是批量并发太高,客户端应做限速与指数退避重试,而不是无限重试把压力堆得更高。

导入限速与重试

  • 客户端按批限速,避免把写入队列打满触发拒绝
  • 遇到拒绝类错误用指数退避重试,不要立即重放
  • 重试前评估重复写入风险:index 动作覆盖安全,create 动作会冲突
  • 导入完成后恢复 refresh_interval 并手动 refresh
  • 逐批记录失败条目,补写时按原始数组下标对应
  • 大批量导入前先在测试索引验证映射与批量参数
导入期间可把副本数临时设为 0 提升写入速度,完成后再调回;这段时间内没有冗余,须选择业务低峰并确认节点健康。
批量请求不需要预先声明动作数量,但动作行与文档行的成对关系必须严格保证;程序生成时建议统一由一个函数拼接,减少手写错行。

易错点

  • 最后一行缺换行会导致解析失败,脚本拼 NDJSON 时注意补尾换行
  • 单批体积过大(如几万条)会超时或被拒绝,按几 MB 级别切批更稳
  • 只判断 HTTP 状态不检查 errors 与 items,会漏掉部分失败并造成数据缺口
  • 动作行与文档行不成对(delete 动作多写了文档行)会直接报解析错误
  • 不恢复 refresh_interval 就让批量任务结束,新数据长时间搜不到,需要恢复并手动 refresh

数据来源与参考

  • Elasticsearch Guide: Bulk API
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌