bulk API可以在单个请求中一次执行多个索引或者删除操作,使用这种方式可以极大的提升性能。
bulk的语法格式是NDJSON(newline delimited JSON)
:
action and meta_data \n
optional source \n
action and meta_data \n
optional source \n
action and meta_data \n
optional source \n
从上面能够看到,两行数据构成了一次操作,第一行是操作类型可以index,create,update,或者delete,第二行就是我们的可选的数据体。使用这种方式批量插入的时候,我们需要设置的它的Content-Type为application/ndjson
。
分别使用index
和create
API,往products
中插入两条数据。
其中index操作无论数据是否存在,都会插入或更新该数据;而create操作不同,当插入的_id
存在于索引中时,create操作会报错:
POST /_bulk
{"index":{"_index":"products", "_id":200} }
{"name":"McCafe", "price":18, "count":20}
{"create":{"_index":"products", "_id":201} }
{"name":"Chicken", "price":12, "count":30}
成功执行:
使用update
API可以批量更新数据:
POST /_bulk
{"update":{"_index":"products", "_id":200} }
{"doc":{"price":100}}
{"update":{"_index":"products", "_id":201} }
{"doc":{"price":200}}
上面的写法,每个操作都要指定Index name(products)
,可以直接使用/products/_bulk
形式,这样每个操作中不再需要指定index名称:
POST /products/_bulk
{"update":{"_id":200} }
{"doc":{"price":111}}
{"delete":{ "_id":201} }
确认数据删除及更新成功:
GET /products/_search
{
"query": {
"match_all": {}
}
}
使用bulk操作时,每个操作之间互不影响,且按顺序执行
如果中间某个操作失败了,不会影响下面操作的执行
执行完成后,会返回每个动作的执行结果
Bulk API也支持乐观并发控制
,指定_if_primary_term
和if_seq_no
即可
Bulk API的使用场景: 一次需要操作很多条数据,将这些操作放到一次执行更高效
上面我们在Kibana中执行了Bulk API操作。接下来介绍CURL的方式
下载数据:
wget https://pingfan.s3.amazonaws.com/files/products.json
products.json
中以ndjson
格式,提供了Bulk API操作所需的数据:
使用CURL来批量插入数据:
curl -XPOST https://elasticsearch-demo-3c803f.es.us-central1.gcp.cloud.es.io/products/_bulk \
-H "Content-Type: application/x-ndjson" \
-u elastic:{your-password} \
--data-binary "@products.json"
/products/_bulk
结尾,这样我们不用在每个操作中都指定index名称了--data-binary
指定了文件路径操作结果:
执行成功后,查看products的shard,发现数据较均匀地分布,这证明routing将数据打的比较散:
如果是Docker搭建的ES,则会有证书信任问题,此时可用-k
参数来解决:
整个批量请求都需要由接收到请求的节点加载到内存中。 批量请求的大小有一个最佳值,大于这个值,性能将不再提升,甚至会下降。 但是最佳值不是一个固定的值,它完全取决于硬件、文档的大小和复杂度、索引和搜索的负载的整体情况。
幸运的是,很容易找到这个 最佳点 :通过批量索引文档,并不断增加批量大小进行尝试。 当性能开始下降,那么你的批量大小就太大了。一个好的办法是开始时将 1,000 到 5,000 个文档作为一个批次, 如果你的文档非常大,那么就减少批量的文档个数。
关注批量请求占用的物理大小往往非常有用, 一个好的批量操作所占用的物理大小约为 5-15 MB。
总结:如果我们有大量的数据,可以将其保存到文件中,使用CURL进行批量插入