Phần 3: BULK API trong ElasticSearch

Các phần trước có đề cập đến sử dụng API cơ bản để CRUD dữ liệu bằng các request đơn lẻ, trong thực tế để tăng tốc độ đánh index và get dữ liệu thì việc sử dụng Bulk API là điều bắt buộc. Để lấy nhiều Document trong một request bạn có thể sử dụng API _mget. Cần truyền vào body request một Array các docs trong đó mỗi Document có thể chỉ ra _index, _type_id

Retreive multiple Documents:

GET /google/_mget
{
    "docs": [
        {"_type": "employee", "_id": 1},
        {"_type": "employee", "_id": 2}
        ]
}

Nếu tất cả các Documents muốn lấy ra có cùng _index_type thì chỉ cần truyền vào một Array các ids chứ không cần docs"

GET /google/employee/_mget
{
    "ids": [1, 2]
}

Cũng theo cách đó bulk API cũng cho phép chúng ta create, index, update hay delete nhiều document trong một single request. Một bulk request body có format hơi khác một chút so với các API ở phần trước, bởi nó tách bạch riêng rẽ phần action, metadata với request body:

{ action: { metadata }}\n
{ request body}\n
{ action: { metadata }}\n
{ request body}\n
...
  • Mỗi dòng kết thúc bởi ký tự break line \n
  • Các dòng phải không được chứa ký tự \n ngoại trừ ở cuối dòng, để thuận lợi cho việc ES sẽ parse request.

Việc tách phần metadata và dữ liệu trong body request làm tăng hiệu năng trong quá trình parse request của ES. Với việc biết trước metadata là gì ES chỉ cần thao tác trên các document có metadata như vậy mà không cần mất công đi parse body request để lấy metadata nữa Example:

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":"My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title":"My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }

Lưu ý rằng toàn bộ bulk request sẽ được load trong bộ nhớ của Node nhận request, vì vậy request càng lớn thì bộ nhớ mà Node này dành cho các request khác càng giảm, Điều tệ hại hơn khi request quá lớn khiến ES xử lý các request khác chậm hoặc Node đó bị đơ do thiếu memory, không những nó không cải thiện được performance mà làm cho performance của ES tệ đi Vậy câu hỏi đặt ra ở đây là size của một bulk request là bao nhiêu thì hợp lý? Không có câu trả lời cụ thể cho câu hỏi trên, nó phụ thuộc vào hardware, document size, complexity, indexing và search load. Tuy nhiên có một cách dễ dàng để bạn có thể tìm ra con số đó. Hãy bắt đầu một request với batch size từ 1000 đến 5000 Documents, nếu Document của bạn quá lớn thì có thể giảm batch size xuống. Thường thì size của một request để bắt đầu test nên rơi vào khoảng từ 5-15MB. Gửi request này liên tuc đên server đồng thời quan sát hệ thống, nếu mọi thứ vẫn ổn thì tăng dần batch size lên cứ thể cho đến khi bạn tìm thấy một giá trị phù hợp cho batch size.