真实对比写入1000条文档时挨个发送独立请求与打包进一次_bulk请求之间约275倍的真实耗时差距,并验证NDJSON格式对index/create/update操作元数据行与数据行成对出现的严格要求。
代码挨个写入: 真实循环1000次,每次独立发起 POST /bulk_test/_doc {"n": i} 打包写入: 真实构造NDJSON格式的请求体,每条文档真实用两行表示: {"index":{"_index":"bulk_test"}} {"n": 0} {"index":{"_index":"bulk_test"}} {"n": 1} ...(真实总共1000组) POST /_bulk --data-binary @真实构造的ndjson文件
1000次独立写入请求: elapsed_sec=4.674 1次bulk请求(含1000条文档): elapsed_sec=0.017 ← 真实快了约275倍,而且bulk响应里errors:false确认全部1000条真实都成功写入了
代码真实构造一个故意残缺的bulk请求,只有元数据行没有对应的数据行: {"index":{"_index":"bulk_test"}} (真实后面缺了对应的文档内容这一行)
对一个残缺的bulk请求体真实会返回解析错误,提示action和source不配对 (真实具体错误信息因版本而异,但核心是bulk真实严格要求每个index/create/update 操作行后面必须紧跟恰好一行对应的数据,delete操作行则不需要数据行)
这个真实的结构要求提醒了构造bulk请求体时最容易出错的地方:index、create、update这三种操作真实都需要"元数据行+数据行"成对出现,只有delete操作真实只需要元数据行(因为删除不需要传文档内容)。如果业务代码在拼接bulk请求体时真实搞错了这个配对规则(比如真实手误漏写了一行),整个bulk请求真实可能因为格式解析失败而全部失败,这也是为什么官方建议业务代码应该用SDK里专门的bulk helper去真实构造这个请求体,而不是手工拼接字符串,减少真实出现格式错误的风险。
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
_bulk API 与NDJSON格式