批量操作

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

bulk API测试

分别使用indexcreate 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} 

成功执行:

image-20220709213335136

使用update API可以批量更新数据:

POST /_bulk
{"update":{"_index":"products", "_id":200} }
{"doc":{"price":100}}
{"update":{"_index":"products", "_id":201} }
{"doc":{"price":200}}

image-20220709213614003

上面的写法,每个操作都要指定Index name(products),可以直接使用/products/_bulk形式,这样每个操作中不再需要指定index名称:

POST /products/_bulk
{"update":{"_id":200} }
{"doc":{"price":111}}
{"delete":{ "_id":201} }

image-20220709213729327

确认数据删除及更新成功:

GET /products/_search
{
  "query": {
    "match_all": {}
  }
}

总结

  1. 使用bulk操作时,每个操作之间互不影响,且按顺序执行

  2. 如果中间某个操作失败了,不会影响下面操作的执行

  3. 执行完成后,会返回每个动作的执行结果

  4. Bulk API也支持乐观并发控制,指定_if_primary_termif_seq_no即可

  5. Bulk API的使用场景: 一次需要操作很多条数据,将这些操作放到一次执行更高效

使用CURL执行

上面我们在Kibana中执行了Bulk API操作。接下来介绍CURL的方式

下载数据:

wget https://pingfan.s3.amazonaws.com/files/products.json

products.json中以ndjson格式,提供了Bulk API操作所需的数据:

image-20220709214129626

使用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"
  • 注意URL后面以/products/_bulk 结尾,这样我们不用在每个操作中都指定index名称了
  • --data-binary指定了文件路径

操作结果:

image-20220709214328591

执行成功后,查看products的shard,发现数据较均匀地分布,这证明routing将数据打的比较散:

image-20220709214545144


如果是Docker搭建的ES,则会有证书信任问题,此时可用-k参数来解决:

image-20220724234946714

Bulk操作的最佳实践

整个批量请求都需要由接收到请求的节点加载到内存中。 批量请求的大小有一个最佳值,大于这个值,性能将不再提升,甚至会下降。 但是最佳值不是一个固定的值,它完全取决于硬件、文档的大小和复杂度、索引和搜索的负载的整体情况。

幸运的是,很容易找到这个 最佳点 :通过批量索引文档,并不断增加批量大小进行尝试。 当性能开始下降,那么你的批量大小就太大了。一个好的办法是开始时将 1,000 到 5,000 个文档作为一个批次, 如果你的文档非常大,那么就减少批量的文档个数。

关注批量请求占用的物理大小往往非常有用, 一个好的批量操作所占用的物理大小约为 5-15 MB。

总结:如果我们有大量的数据,可以将其保存到文件中,使用CURL进行批量插入