이전 문서 curl을_이용한_간단한_ElasticSearch_사용 에서 단건 insert를 이용해 데이터를 적재하는 예제를 다뤘는데, 단건 insert를 반복하는 것은 ElasticSearch의 성능을 최대한으로 끌어내지 못하는 한계점을 가지고 있다. 그래서 bulk API를 이용해서 대량 insert를 하는 예제를 다뤄보겠다.
bulk API는 기존의 doc API와 달리 인덱스를 미리 생성해두어야 한다.
curl -s -X PUT localhost:9200/test_index > /dev/null
bulk API는 다음과 같이 사용할 수 있다.
curl -s -X POST localhost:9200/test_index/_bulk -H "Content-Type: application/json" -d '
{"index": {"_id": "id1"}}
{"num": 1}
{"index": {"_id": "id2"}}
{"num": 2}
'
위 예제와 같이 bulk API의 요청 payload는 짝수 개의 줄로 구성되어 있다. 홀수 줄에서는 insert하려는 데이터의 메타데이터를 지정하고 짝수 줄에서는 데이터를 지정한다. 그러므로 "id1"이라는 id를 가지는 문서 {"num": 1}이 적재되는 것이다.
대량 데이터를 command-line argument로 길게 쓰기 어렵다. 그러므로 표준입력을 redirect하는 방법을 살펴보자.
-d '...' 옵션 대신에 --data-binary @-를 이용하고 표준 입력을 받아서 사용하면 된다.
(echo '{"index": {"_id": "id1"}}';
echo '{"num": 1}';
echo '{"index": {"_id": "id2"}}';
echo '{"num": 2}') | curl -s -X POST localhost:9200/test_index/_bulk -H "Content-Type: application/json" --data-binary @-
echo의 나열 대신 Bash의 while loop로 바꿔본다.
total_count=1000
i=0
(while [ "$i" -lt "$total_count" ]; do
echo '{"index": {"_id": "'"$i"'"}}'
echo '{"num": '"$i"'}'
i=$((i+1))
done) | curl -s -X POST localhost:9200/test_index/_bulk -H "Content-Type: application/json" --data-binary @- > /dev/\
null
엄밀한 성능 평가를 해본 건 아니지만, 기존 doc API를 이용한 단건 insert는 대략 130 TPS를 얻을 수 있었고, bulk API를 이용한 대량 insert는 대략 66000 TPS를 얻을 수 있었다. 그러므로 500배 이상의 성능 향상이 생겼다고 볼 수 있다. 500배라는 상대적인 비율이 중요한 게 아니라 비교할 수 없을 정도로 성능 차이가 많이 나므로 대용량 데이터는 bulk API를 이용해서 적재하는 게 바람직하다는 의미이다.