엘라스틱서치 벌크 최적화
2022-04-28벌크 인서트 최적화
GIS 공공데이터를 가공해서 1년치 이상 데이터를 꾸준하게 ES에 입력해야되는 상황에 조금더 효율적으로 빠르게 넣는 방법을 찾으면서 정리한 내용입니다.
결론
- 리소스 특히 메모리/디스크 IO 많이 늘려라. 돈을 많이 써라 ㅡㅡ;
요약
- 벌크 데이터가 수십메가를 넘지 않는것이 좋다? (대단위 입력을 위한 건데 당연한 소리를???)
- 클러스터의 모든 리소스를 쓰면 좋지 않다. (검색에 방해되니까 적당한 리소스를 써라???)
- 데이터 갱신주기를 늦춰라 (자주 쓰지 않으면 좋긴할텐데, 1000TPS가 넘는 애들은 무리인듯)
- 벌크할때는 index.number_of_replicas를 0으로 설정하는 것이 좋다 ( 넣을때는 빠른데, 다넣고 나서 리플리카를 설정하면 결국 조삼모사아닌가?)
- 벌크 시작전에 index.refresh_interval 초기화 시키고 완료된 이후에 재설정해라 ( 결국 조삼모사)
- 시스템 캐시는 컴퓨터의 메모리 절반 이상을 파일 시스템 캐시 제공 ( 즉! 메모리를 늘려라)
- 자동인덱스를 사용하면 샤드별로 검색하지 않아 빠르다. (이건 해볼만한데, 나중에 샤드할려면 조삼모사잖아?)
- indices.memory.index_buffer_size = 512M 설정해라 (즉, 메모리를 늘려라)
- 빠른 디스크IO = SSD를 써라 (이건 애저나 아마존 비용측면,IDC에서 사용할때는 고려해야되겠네)
- 원격파일 시스템 NTFS,SMB,Amazon의 Elastic Block Storage와 같은 가상화된 스토리지 사용을 주의해라 (느리다, 당근말밥이지)
- 2개 이상의 클러스터를 사용하고 읽기/쓰기를 분리해라 (리소스 분산측면에서 당연한소리)
Thread_pool type
* generic : 일반 용도(예: background node discovery) 쓰레드 풀 타입은 cached 다.
* index : 인덱싱/삭제 용도. available_processors 사이즈의 fixed 타입, queue_size 는 200이다.
* search : count/search 용도. fixed 타입, int((# of available_processors\*3)/2)+1 사이즈, queue_size 는 1000이다.
* suggest : suggest 용도. fixed 타입, available_processors 사이즈, queue_size는 1000
* get : get 용도. fixed 타입, available_processors 사이즈, queue_size는 1000
* bulk : bulk 용도. fixed 타입, available_processors 사이즈, queue_size는 50
* percolate : 거르는(?) 용도. fixed 타입, available_processors 사이즈, queue_size 는 1000
* snapshot : 스냅샷/복원 용도. scaling 타입, keep-alive 5m이고 min(5, (available_processors)/2) 사이즈
* warmer : segment warm-up 용도. scaling 타입 keep-alive 5m 이고 min(5, (available_processors)/2) 사이즈
* refresth : refresh 용도. scaling 타입 keep-alive 5m min(10, (available_processors)/2) 사이즈
* listener : 주로 java client 실행용으로 listener threaded 가 true 로 설정 되었을 때 사용되는 용도. scaling 타입, 기본 사이즈는 min(10, (available_processors)/2)
아래는 엘라스틱서치 튜닝관련 공식 문서의 내용
Tune for indexing speed
대량 요청은 단일 문서 색인 요청보다 훨씬 더 나은 성능을 제공합니다. 대량 요청의 최적의 크기를 알려면 단일 샤드가 있는 단일 노드에서 벤치마크를 실행해야 합니다. 먼저 100개의 문서를 한 번에 인덱싱한 다음, 200개의 문서, 400개의 문서 등을 벤치마크 실행마다 대량 요청에서 두 배로 인덱싱합니다. 인덱싱 속도가 안정되기 시작하면 데이터에 대한 대량 요청의 최적 크기에 도달했다는 것을 알 수 있습니다. 동률일 경우 서류가 너무 많은 것보다는 너무 적은 방향으로 오차가 나는 것이 좋다. 대량 요청이 너무 크면 동시에 전송될 때 클러스터에 메모리 부담이 가중될 수 있으므로, 더 큰 요청이 더 잘 수행되더라도 요청당 수십 메가바이트를 넘지 않도록 하는 것이 좋습니다.
대량 요청을 보내는 단일 스레드는 Elastic 검색 클러스터의 인덱싱 용량을 최대화할 수 없습니다. 클러스터의 모든 리소스를 사용하려면 여러 스레드 또는 프로세스에서 데이터를 전송해야 합니다. 이렇게 하면 클러스터의 리소스를 더 잘 활용할 수 있을 뿐만 아니라 각 fsync의 비용을 줄일 수 있습니다. TOO_MANY_REQUESTS(429) 응답 코드(EsRejected)를 확인하십시오.실행Java 클라이언트의 예외)는 Elastic 검색이 현재 인덱싱 속도를 따라갈 수 없음을 알려주는 방법입니다. 이 경우 인덱싱을 잠시 중지한 후 다시 시도해야 합니다. 이상적으로는 랜덤 지수 백오프를 사용하는 것이 좋습니다. 대량 요청의 크기 조정과 마찬가지로 테스트만 최적의 작업자 수를 알 수 있습니다. 이는 클러스터에서 I/O 또는 CPU가 포화 상태가 될 때까지 작업자 수를 점진적으로 증가시켜 테스트할 수 있습니다.
새로 고침이라고 하는 검색에 변경 사항을 표시하는 작업은 비용이 많이 들고 인덱싱 작업이 진행되는 동안 자주 호출하면 인덱싱 속도가 저하될 수 있습니다. 기본적으로 Elasticsearch는 주기적으로 1초마다 인덱스를 새로 고치지만 지난 30초 동안 하나 이상의 검색 요청을 받은 인덱스에 대해서만 업데이트됩니다. 검색 트래픽이 없거나 매우 적은 경우(예: 5분마다 검색 요청이 1개 미만) 인덱싱 속도를 최적화하려는 경우 최적의 구성입니다. 이 동작은 검색이 수행되지 않을 때 기본적으로 대량 인덱싱을 자동으로 최적화하기 위한 것입니다. 이 동작을 해제하려면 새로 고침 간격을 명시적으로 설정하십시오. 반면 인덱스에 정기적인 검색 요청이 있는 경우 이 기본 동작은 Elastic 검색이 1초마다 인덱스를 새로 고친다는 의미입니다. 문서가 색인화될 때까지의 시간을 늘릴 수 있는 경우 index.refresh_interval을 더 큰 값(예: 30초)으로 늘리면 색인 속도가 향상될 수 있습니다.
Elastic 검색에 한꺼번에 로드하려는 많은 양의 데이터가 있는 경우 인덱싱 속도를 높이기 위해 index.number_of_replicas를 0으로 설정하는 것이 좋습니다. 복제본이 없다는 것은 단일 노드가 손실될 수 있다는 것을 의미하므로, 문제가 발생할 경우 이 초기 로드를 재시도할 수 있도록 데이터가 다른 곳에 상주하는 것이 중요합니다. 초기 로드가 완료되면 index.number_of_replicas를 원래 값으로 다시 설정할 수 있습니다. 인덱스 설정에서 index.refresh_interval이 구성되어 있으면 초기로드가 완료되면이 초기로드 중에 index.refresh_interval을 설정 해제하고 원래 값으로 다시 설정하는 데 도움이 될 수 있습니다.
인덱스 설정에서 index.refresh_interval이 구성되어 있으면 초기로드가 완료되면이 초기로드 중에 index.refresh_interval을 설정 해제하고 원래 값으로 다시 설정하는 데 도움이 될 수 있습니다.
파일 시스템 캐시는 I/O 작업을 버퍼링하는 데 사용됩니다. Elastic search를 실행하는 컴퓨터의 메모리 절반 이상을 파일 시스템 캐시에 제공해야 합니다.
명시적 ID가 있는 문서를 색인화할 때, Elasticsearch는 동일한 ID를 가진 문서가 동일한 샤드에 이미 존재하는지 확인해야 하는데, 이는 비용이 많이 들고 색인이 커질수록 비용이 더 많이 든다. 자동 생성된 ID를 사용하면 Elastic 검색이 이 검사를 건너뛸 수 있으므로 인덱싱 속도가 빨라집니다.
인덱싱이 I/O 바인딩된 경우 파일 시스템 캐시에 더 많은 메모리를 제공하거나(위 참조) 더 빠른 드라이브를 구입하는 방법을 조사해야 합니다. 특히 SSD 드라이브는 회전 디스크보다 성능이 더 뛰어난 것으로 알려져 있습니다. 항상 로컬 스토리지를 사용해야 하며 NFS 또는 SMB와 같은 원격 파일 시스템은 피해야 합니다. 또한 Amazon의 Elastic Block Storage와 같은 가상화된 스토리지에 주의하십시오. 가상화된 스토리지는 Elastic 검색과 매우 잘 작동하며, 설정이 매우 빠르고 간단하기 때문에 매력적이지만, 전용 로컬 스토리지에 비해 지속적으로 속도가 느리기도 합니다. EBS에 인덱스를 추가하는 경우 프로비저닝된 IOPS를 사용해야 합니다. 그렇지 않으면 작업이 빠르게 제한될 수 있습니다.
노드가 무거운 인덱싱만 수행하는 경우 indices.memory.index_buffer_size가 무거운 인덱싱을 수행하는 샤드당 최대 512MB 인덱싱 버퍼를 제공할 수 있을 만큼 충분히 큰지 확인하십시오(인덱싱 성능이 일반적으로 향상되지 않음). Elasticsearch는 해당 설정 (자바 힙 또는 절대 바이트 크기의 백분율)을 취하여 모든 활성 파편에 대해 공유 버퍼로 사용합니다. 매우 활동적인 조각은 경량 인덱싱을 수행하는 조각보다 자연스럽게이 버퍼를 더 많이 사용합니다. 기본값은 10%로 넉넉한 경우가 많습니다. 예를 들어 JVM에 10GB 메모리를 제공하면 인덱스 버퍼에 1GB가 제공되므로 인덱싱이 심한 두 개의 샤드를 호스팅할 수 있습니다.
단일 클러스터 내에서 인덱싱 및 검색은 자원을 놓고 경쟁할 수 있습니다. 두 개의 클러스터를 설정하고, 한 클러스터에서 다른 클러스터로 데이터를 복제하도록 교차 클러스터 복제를 구성하고, 모든 검색을 팔로어 인덱스가 있는 클러스터로 라우팅함으로써, 검색 활동은 더 이상 리더 인덱스를 호스트하는 클러스터의 인덱싱에서 자원을 훔치지 않을 것이다.
또한 디스크 사용을 위한 튜닝에 설명된 많은 전략은 인덱싱 속도를 향상시킵니다.