데이터 적재 권장 사항과 성능 튜닝
데이터 적재는 Apache Doris의 가장 중요한 기능 중 하나입니다. 데이터 적재 효율은 실시간 분석의 적시성과 시스템 안정성을 직접 좌우합니다. 이 문서에서는 일반적인 비즈니스 시나리오를 바탕으로 바로 적용할 수 있는 권장 사항을 먼저 소개한 다음, 데이터 적재의 내부 동작과 튜닝 방법을 자세히 설명하여 다음 작업을 돕습니다.
- 비즈니스 특성에 맞는 데이터 적재 방식 선택
- 테이블 설계, 배치 처리, 버킷팅, 메모리, 동시성에 대한 합리적인 의사 결정
- 빈번한 소량 데이터 적재, 쓰기 증폭, Memtable OOM과 같은 일반적인 문제 예방
- 비즈니스에 맞는 지연 시간과 처리량의 균형 확보
빠른 탐색
| 고려 사항 | 권장 사항 | 관련 섹션 |
|---|---|---|
| 데이터 적재 방식 선택 | 데이터 소스와 실시간 요구 사항에 따라 선택 | 적절한 데이터 적재 방식 선택 |
| 테이블 모델 | Duplicate Key 모델 우선 사용 | 테이블 모델과 인덱스 |
| 파티셔닝과 버킷팅 | 단일 Tablet 크기를 1~10 GB로 유지 | 파티셔닝 및 버킷팅 구성 |
| 랜덤 버킷팅 | load_to_single_tablet을 활성화하여 처리량 향상 | 랜덤 버킷팅 데이터 적재 최적화 |
| 빈번한 소량 데이터 적재 | 클라이언트 측 배치 처리와 Group Commit 병행 | 배치 처리 전략 |
| 데이터 적재당 파티션 수 | Memtables가 과도하게 늘어나지 않도록 소수로 제한 | 파티션 데이터 적재와 메모리 제어 |
| 대용량 데이터 적재 | 배치로 나누고 각 배치를 100 GB 이하로 유지 | 대규모 데이터의 배치 적재 |
| Broker Load 동시성 | 압축 파일이나 컬럼형 파일을 분할하여 동시성 확보 | Broker Load 동시성 |
| Stream Load 동시성 | BE당 동시성을 128 미만으로 유지 | Stream Load 동시성 |
적절한 데이터 적재 방식 선택
Doris는 핵심 워크플로를 공유하면서도 서로 다른 시나리오에 최적화된 여러 데이터 적재 방식을 제공합니다. 데이터 소스와 비즈니스 요구 사항에 따라 선택하세요.
| 데이터 적재 방식 | 프로토콜 | 실행 모드 | 일반적인 데이터 소스 | 적용 시나리오 |
|---|---|---|---|---|
| Stream Load | HTTP | 동기 | 로컬 파일, 데이터 스트림 | 실시간 쓰기(애플리케이션이 푸시하는 데이터 등) |
| Broker Load | SQL | 비동기 | HDFS, S3 및 기타 외부 스토리지 | 대규모 배치 데이터 적재 |
| Routine Load | SQL | 비동기 스트리밍 | Kafka | Exactly-Once를 지원하는 메시지 큐 데이터의 실시간 동기화 |
| Insert Into / Select | SQL | 동기/비동기 | Doris 테이블, Hive, MySQL, S3 TVF | ETL 작업, 외부 데이터 통합 |
| MySQL Load | MySQL LOAD DATA | 동기 | 로컬 CSV 파일 | MySQL 사용자의 소규모 테스트 또는 마이그레이션(FE가 Stream Load로 전달) |
데이터 적재 권장 사항
다음 섹션에서는 데이터 적재 시 흔히 고려하는 사항을 다루고, 바로 적용할 수 있는 권장 사항을 제공합니다.
테이블 모델과 인덱스
테이블 모델 선택
Duplicate Key 모델을 우선 사용하세요.
- 집계나 중복 제거 없이 원시 데이터만 저장하므로 데이터 적재 경로가 가장 짧습니다.
- 데이터 적재와 쿼리 성능 모두에서 다른 모델보다 우수합니다.
- Aggregate 모델은 Key 컬럼을 기준으로 집계해야 하고, Unique Key 모델은 중복을 제거해야 합니다. 두 모델 모두 MemTable 단계에서 BE 측에 추가 연산(정렬, 중복 제거)이 발생하므로 CPU 및 메모리 사용량이 늘어납니다.
실제로 Key를 기준으로 집계하거나 중복을 제거해야 할 때만 Aggregate 또는 Unique Key 모델을 선택하세요. 자세한 내용은 데이터 모델을 참조하세요.
인덱스 관리
인덱스(비트맵 인덱스, 역색인 등)는 데이터 적재 중 동기적으로 갱신해야 하므로 쓰기 시 유지 관리 비용이 늘어납니다. 권장 사항은 다음과 같습니다.
- 자주 쿼리하는 필드에만 인덱스를 생성하세요.
- 불필요한 인덱스를 피하세요. 쓰기 중 BE에서 수행하는 인덱스 생성과 검증을 줄이면 CPU 및 메모리 사용량을 낮추고 데이터 적재 처리량을 높일 수 있습니다.
파티셔닝 및 버킷팅 구성
파티셔닝과 버킷팅은 BE 노드 간 데이터 분산 방식과 병렬 처리 수준을 결정하며, 데이터 적재 및 쿼리 성능에 직접적인 영향을 줍니다.
단일 Tablet 크기: 1-10 GB
단일 Tablet 크기를 1~10 GB 범위로 유지하세요.
| Tablet 크기 | 영향 |
|---|---|
| 너무 작음 | 집계 효과가 낮고 메타데이터 관리 부담 증가 |
| 너무 큼 | 복제본 마이그레이션과 보충이 어려움 |
| 1-10 GB(권장) | 데이터 적재, 쿼리, 복제본 관리 간 균형 확보 |
버킷 수 계산식은 bucket count = total data size / (1-10 GB)입니다. 여기에 적절한 버킷 키(예: 무작위 값이 있는 컬럼)를 함께 사용하면 데이터 쏠림을 방지하고 BE 노드 간 부하를 균등하게 분산하여 병렬 쓰기 효율을 높일 수 있습니다.
자세한 내용은 데이터 분산을 참조하세요.
파티션 설계: 분산 및 메모리 부담 완화
비즈니스 쿼리 패턴(예: 시간 또는 지역)에 따라 파티션을 나누세요. 그러면 데이터 적재 중 대상 파티션에만 데이터가 분산되므로 관련 없는 파티션의 메타데이터와 파일을 처리하지 않아도 됩니다. 또한 다음 사항을 고려하세요.
- 여러 파티션에 동시에 쓰면 많은 Tablet이 활성화됩니다. 각 Tablet은 자체 MemTable을 사용하므로 BE의 메모리 부담이 크게 증가합니다.
- 메모리가 부족하면 조기 Flush가 발생하여 작은 Segment 파일이 많이 생성되고, 잦은 Compaction과 쓰기 증폭으로 이어집니다.
활성 파티션 수를 제한하면(예: 일자별로 데이터 적재) 동시에 활성화되는 Tablet 수를 줄이고 메모리 부담을 완화할 수 있습니다. 또한 더 큰 Segment 파일을 생성하고 Compaction 부하를 줄여 병렬 쓰기 효율과 이후 쿼리 성능을 높일 수 있습니다.
랜덤 버킷팅 데이터 적재 최적화
랜덤 버킷팅을 사용할 때는 load_to_single_tablet=true를 설정하여 단일 Tablet 데이터 적재 모드를 활성화할 수 있습니다.
- 여러 Tablet으로 분산하는 과정을 거치지 않고 단일 Tablet에 직접 데이터를 씁니다. 따라서 Tablet 분산 계산에 드는 CPU 오버헤드와 BE 간 RPC 전송 오버헤드가 사라집니다.
- 쓰기를 단일 Tablet에 집중하면 작은 Segment 파일의 생성이 줄어들고, 잦은 Compaction으로 인한 쓰기 증폭을 방지할 수 있습니다.
- 대규모 데이터 적재의 동시성과 처리량이 크게 향상됩니다.
자세한 내용은 랜덤 버킷팅을 참조하세요.
배치 처리 전략
각 데이터 적재는 독립적인 트랜잭션이며, FE Edit Log에 쓰기(메타데이터 변경 기록)와 BE MemTable을 디스크로 flush하는 작업(Segment 파일 생성)을 수반합니다. 빈번한 소규모 배치 데이터 적재(KB 수준)는 다음 문제를 일으킵니다.
- FE Edit Log에 자주 쓰게 되어 FE 디스크 I/O가 증가합니다.
- BE MemTable이 자주 flush되어 작은 Segment 파일이 많이 생성됩니다.
- Compaction이 자주 발생하여 심각한 쓰기 증폭으로 이어집니다.
클라이언트 측과 서버 측 배치 처리를 함께 사용하면 이러한 문제를 완화할 수 있습니다.
| 배치 처리 방식 | 적용 시나리오 | 권장 사항 |
|---|---|---|
| 클라이언트 측 배치 처리 | 클라이언트에서 제어하는 배치 쓰기 | 클라이언트에 데이터를 수백 MB에서 수 GB까지 모은 후 데이터 적재를 시작하세요. 여러 작은 트랜잭션을 하나의 큰 트랜잭션으로 대체하면 FE Edit Log 쓰기와 BE MemTable flush 빈도가 줄어들어 스토리지 단편화와 이후 Compaction의 리소스 소비를 방지할 수 있습니다. |
| 서버 측 배치 처리(Group Commit) | 동시성이 높고 데이터양이 적은 데이터 적재 | Group Commit을 활성화하여 서버가 짧은 시간 동안 여러 소규모 배치를 하나의 트랜잭션으로 병합하도록 하세요. 병합된 대규모 트랜잭션은 더 큰 Segment 파일을 생성하여 백그라운드 Compaction 부담을 줄입니다. 로그나 IoT 데이터처럼 빈번한 소규모 배치 시나리오에 특히 적합합니다. |
파티션 데이터 적재와 메모리 제어
데이터 적재 중 BE는 먼저 메모리 내 MemTable(기본값 200 MB)에 데이터를 씁니다. MemTable이 가득 차면 비동기적으로 디스크에 flush하여 Segment 파일을 생성합니다. 각 Tablet은 메모리에 활성 MemTable 하나를 가지므로, 한 번의 데이터 적재가 포함하는 파티션 수는 메모리 사용량에 직접적인 영향을 줍니다.
- 파티션이 너무 많으면 활성 Tablet이 많아지고, 그에 따라 활성 MemTables가 늘어나 메모리 사용량이 증가합니다.
- 메모리 사용량이 너무 높으면 프로세스 OOM을 방지하기 위해 조기 flush가 발생합니다.
- 조기 flush는 작은 파일을 많이 생성하여 데이터 적재 성능을 더욱 떨어뜨립니다.
안정적인 데이터 적재 처리량을 확보하려면 다음을 따르세요.
- 파티션을 순서대로 적재하세요. 예를 들어 일자별로 적재하면 데이터 쓰기를 단일 파티션에 집중할 수 있어 MemTable 분산과 flush 횟수가 줄고, 메모리 단편화와 I/O 부담도 낮아집니다.
- 한 번의 데이터 적재에 포함되는 파티션 수를 엄격히 제한하세요. MemTables가 너무 많아 조기 flush가 발생하는 것을 방지할 수 있습니다.
대규모 데이터의 배치 적재
파일이 많고 데이터양이 매우 클 때는 배치로 나누어 적재하세요. 재시도 비용을 줄이고 BE 메모리와 디스크에 부하가 집중되는 것을 방지할 수 있습니다.
| 데이터 소스 | 권장 데이터 적재 방식 | 권장 배치 크기 |
|---|---|---|
| HDFS 또는 객체 스토리지 등의 원격 파일 | Broker Load | 각 배치를 100 GB 이하로 유지 |
| 대용량 로컬 파일 | Doris streamloader 도구(자동 배치 처리) | 도구에서 자동으로 제어 |
Broker Load 동시성
동시성 전략은 파일 유형에 따라 다릅니다.
- 압축 파일 / Parquet / ORC 파일: 데이터 적재 전에 여러 작은 파일로 분할하여 동시에 적재할 수 있도록 하세요.
- 압축되지 않은 CSV 및 JSON 파일: Doris가 내부적으로 파일을 자동 분할하여 동시에 적재합니다.
동시성 전략에 대해서는 Broker Load 구성 매개변수를 참조하세요.
Stream Load 동시성
Stream Load 동시성은 BE 스레드 풀 매개변수에 의해 제한됩니다. 다음 기준을 따르세요.
| 매개변수 / 기준 | 권장값 | 설명 |
|---|---|---|
| BE당 동시성(권장 상한) | 128 이하 | BE의 webserver_num_workers로 제어합니다. 이를 초과하면 웹 서버 스레드가 고갈되어 데이터 적재 성능이 저하될 수 있습니다. |
| BE당 동시성(절대 상한) | 512를 초과해서는 안 됨 | doris_max_remote_scanner_thread_pool_thread_num으로 제어합니다. 이를 초과하면 BE 프로세스가 응답하지 않을 수 있습니다. |
낮은 지연 시간이 필요한 시나리오의 동시성 조정
실시간 모니터링처럼 낮은 지연 시간이 필요한 시나리오에서는 다음을 따르세요.
- 리소스 경합을 방지하도록 동시성을 적절히 낮추세요.
- Group Commit의 비동기 모드(
async_mode)를 함께 사용하여 작은 트랜잭션을 병합하고 트랜잭션 커밋 지연 시간을 줄이세요.
Doris 데이터 적재 내부 동작 살펴보기
다음 내부 동작을 이해하면 복잡한 시나리오에서 더 나은 튜닝 결정을 내릴 수 있습니다.
설계 철학
Doris 데이터 적재는 분산 아키텍처를 기반으로 하며, 주로 Frontend(FE) 및 Backend(BE) 노드가 관여합니다.
- FE: 메타데이터 관리, 쿼리 파싱, 작업 스케줄링, 트랜잭션 조정을 담당합니다.
- BE: 실제 데이터 저장, 연산, 쓰기 작업을 담당합니다.
데이터 적재 설계는 실시간 쓰기, 스트리밍 동기화, 배치 데이터 적재, 외부 데이터 소스 통합 등 다양한 비즈니스 요구를 충족하는 것을 목표로 합니다. 핵심 원칙은 다음과 같습니다.
| 설계 목표 | 구현 방식 |
|---|---|
| 일관성과 원자성 | 각 데이터 적재 작업은 하나의 트랜잭션으로, 데이터 쓰기의 원자성을 보장하고 부분 쓰기를 방지합니다. Label 메커니즘은 데이터 손실이나 중복이 없도록 보장합니다. |
| 유연성 | 다양한 데이터 소스(로컬 파일, HDFS, S3, Kafka 등)와 형식(CSV, JSON, Parquet, ORC 등)을 지원하여 여러 시나리오에 대응합니다. |
| 효율성 | 분산 아키텍처로 데이터를 병렬 처리하며, 여러 BE 노드가 동시에 데이터를 처리하여 처리량을 높입니다. |
| 간편성 | 경량 ETL 기능을 제공하여 데이터 적재 중 데이터를 정제하고 변환할 수 있으므로 외부 도구에 대한 의존도를 줄입니다. |
| 유연한 모델링 | Duplicate Key, Unique Key, Aggregate Key 모델을 지원하여 데이터 적재 중 데이터를 집계하거나 중복을 제거할 수 있습니다. |
공통 데이터 적재 워크플로
데이터 적재 방식(Stream Load, Broker Load, Routine Load 등)에 관계없이 핵심 워크플로는 기본적으로 동일합니다.
-
데이터 적재 작업 제출
- 클라이언트(예: HTTP, JDBC 또는 MySQL 클라이언트)를 통해 데이터 적재 요청을 제출하면서 데이터 소스(예: 로컬 파일, Kafka 토픽 또는 HDFS 파일 경로), 대상 테이블, 파일 형식, 데이터 적재 매개변수(예: 구분자 및 오류 허용 범위)를 지정합니다.
- 각 작업에 고유한 Label을 지정하여 작업을 식별하고 멱등성을 지원할 수 있습니다(중복 데이터 적재 방지). 예를 들어 Stream Load에서는 HTTP 헤더로 Label을 지정합니다.
- Doris Frontend(FE)가 요청을 수신하고, 권한을 검증하고, 대상 테이블이 존재하는지 확인한 다음 데이터 적재 매개변수를 파싱합니다.
-
작업 할당 및 조정
- FE는 테이블의 파티셔닝 및 버킷팅 규칙을 바탕으로 데이터 분산을 분석하고, 데이터 적재 계획을 생성한 다음 Backend(BE) 노드를 Coordinator로 선택하여 전체 작업을 조정하도록 합니다.
- Stream Load처럼 BE에 직접 제출하면 해당 BE가 Coordinator 역할을 할 수 있지만, 여전히 FE에서 메타데이터(예: 테이블 스키마)를 가져와야 합니다.
- 데이터 적재 계획은 병렬 처리를 통해 효율을 높일 수 있도록 여러 BE 노드에 데이터를 분산합니다.
-
데이터 읽기 및 분산
- Coordinator BE가 데이터 소스에서 데이터를 읽습니다(예: Kafka에서 메시지 가져오기, S3에서 파일 읽기 또는 HTTP 데이터 스트림 직접 수신).
- Doris는 데이터 형식을 파싱하며(예: CSV 분할 또는 JSON 파싱), 다음과 같은 사용자 정의 경량 ETL 작업을 지원합니다.
- 사전 필터링: 원시 데이터를 필터링하여 처리 오버헤드를 줄입니다.
- 컬럼 매핑: 소스 컬럼과 대상 테이블 컬럼 간의 대응 관계를 조정합니다.
- 데이터 변환: 표현식을 사용하여 데이터를 처리합니다.
- 사후 필터링: 변환된 데이터를 필터링합니다.
- 파싱 후 Coordinator BE는 파티셔닝 및 버킷팅 규칙에 따라 여러 하위 Executor BE에 데이터를 분산합니다.
-
데이터 쓰기
- 데이터가 여러 BE 노드로 분산되어 메모리 내 테이블(MemTables)에 기록되고 Key 컬럼을 기준으로 정렬됩니다. Aggregate 또는 Unique Key 모델에서는 Doris가 Key를 기준으로 집계하거나 중복을 제거합니다(SUM, REPLACE 등 사용).
- MemTable이 가득 차거나(기본값 200 MB) 작업이 끝나면 데이터가 비동기적으로 디스크에 기록되어 Rowset을 구성하는 컬럼형 Segment 파일이 생성됩니다.
- 각 BE는 할당된 데이터를 독립적으로 처리하고, 쓰기가 완료되면 Coordinator에 상태를 보고합니다.
-
트랜잭션 커밋 및 게시
- Coordinator가 FE에 트랜잭션 커밋(Commit)을 요청합니다. FE는 과반수의 복제본에 쓰기가 성공했는지 확인한 후 BE에 데이터 버전을 게시하도록 알립니다(Publish Version). BE Publish가 성공하면 FE는 트랜잭션을 VISIBLE로 표시하고 데이터를 쿼리할 수 있게 됩니다.
- 실패하면 FE가 롤백을 실행하여 임시 데이터를 제거하고 데이터 일관성을 보장합니다.
-
결과 반환
- 동기 방식(예: Stream Load 및 Insert Into)은 성공/실패 상태와 오류 세부 정보(예: ErrorURL)를 포함한 데이터 적재 결과를 직접 반환합니다.
- 비동기 방식(예: Broker Load)은 작업 ID와 Label을 반환합니다.
SHOW LOAD를 사용하여 진행 상황, 오류 행 수, 세부 정보를 확인할 수 있습니다. - 작업은 감사 로그에 기록되어 나중에 추적할 수 있습니다.
MemTable forwarding
MemTable forwarding은 Apache Doris 2.1.0에서 도입된 최적화로, INSERT INTO...SELECT 데이터 적재 성능을 크게 높입니다.
- 기존 흐름의 병목: Sink 노드는 데이터를 Block 형식으로 인코딩한 후 Ping-pong RPC를 통해 하위 노드로 전송해야 합니다. 이 과정에서 인코딩과 디코딩이 여러 차례 발생하여 오버헤드가 증가합니다.
- 최적화: Sink 노드가 MemTables를 직접 처리하여 Segment 데이터를 생성하고 Streaming RPC로 전송합니다. 이를 통해 인코딩/디코딩과 전송 대기를 줄이고, 더 정확한 메모리 역압을 제공합니다.
- 성능 향상: 공식 테스트에서 데이터 적재 시간은 단일 복제본 환경에서 36%, 복제본이 세 개인 환경에서 54%로 줄었으며, 전체 성능은 100% 넘게 향상되었습니다.
- 적용 범위: 현재 이 기능은 스토리지와 컴퓨팅이 통합된 배포 모드에서만 지원됩니다.
컴퓨팅과 스토리지가 분리된 아키텍처의 데이터 적재
컴퓨팅과 스토리지가 분리된 아키텍처에서는 데이터 저장과 트랜잭션 관리의 분리를 중심으로 데이터 적재를 최적화합니다.
- 데이터 저장
- BE는 데이터를 영구 저장하지 않습니다. MemTable Flush 후 생성된 Segment 파일은 공유 스토리지(예: S3 또는 HDFS)에 직접 업로드됩니다. 객체 스토리지의 높은 가용성과 낮은 비용을 활용하여 탄력적인 확장을 지원합니다.
- BE의 로컬 File Cache는 자주 사용하는 데이터를 비동기적으로 캐시하며, TTL 및 Warmup 전략을 통해 쿼리 캐시 적중률을 높입니다.
- 메타데이터(예: Tablet 및 Rowset 메타데이터)는 BE의 로컬 RocksDB 대신 Meta Service가 FoundationDB에 저장합니다.
- 트랜잭션 처리
- 트랜잭션 관리를 FE에서 Meta Service로 옮겨 FE Edit Log 쓰기 병목을 제거합니다.
- Meta Service는 표준 인터페이스(
beginTransaction,commitTransaction)를 통해 트랜잭션을 관리하며, FoundationDB의 전역 트랜잭션 기능으로 일관성을 보장합니다. - BE Coordinator는 Meta Service와 직접 상호 작용하여 트랜잭션 상태를 기록하고, 원자적 연산으로 충돌과 시간 초과에 따른 회수를 처리합니다. 이를 통해 동기화 로직을 간소화하고 동시성이 높은 소규모 배치 데이터 적재의 처리량을 높입니다.
지연 시간과 처리량 사이의 균형
실제 비즈니스 시나리오에서는 데이터 적재의 지연 시간과 처리량 사이에서 균형을 잡아야 하는 경우가 많습니다.
- 낮은 지연 시간: 최신 데이터를 더 빨리 확인할 수 있지만, 쓰기 배치가 작아지고 쓰기 빈도가 높아지면 백그라운드 Compaction이 더 자주 발생합니다. 이로 인해 CPU, I/O, 메모리를 더 많이 소비하고 메타데이터 관리 부담도 커집니다.
- 높은 처리량: 데이터 적재당 데이터양을 늘리고 데이터 적재 횟수를 줄이면 메타데이터 부담과 백그라운드 Compaction 오버헤드를 크게 낮추어 전체 시스템 성능을 높일 수 있습니다. 다만 데이터를 쓴 후 조회할 수 있게 되기까지의 지연 시간은 늘어납니다.
따라서 비즈니스의 지연 시간 요구 사항을 충족하는 범위에서 데이터 적재당 데이터양을 최대한 늘려 처리량을 높이고 시스템 오버헤드를 줄이세요.
테스트 데이터
Flink 엔드투엔드 지연 시간
이 테스트는 Flink Connector를 배치 쓰기 모드로 사용하며, 엔드투엔드 지연 시간과 데이터 적재 처리량에 초점을 맞춥니다. 배치 처리 간격은 Flink Connector 매개변수인 sink.buffer-flush.interval로 제어합니다. Flink Connector 사용 방법은 Flink-Doris-Connector를 참조하세요.
장비 구성:
- 1 FE: 8코어 CPU, 16 GB 메모리
- 3 BE: 16코어 CPU, 64 GB 메모리
데이터 세트:
- TPCH lineitem 데이터
배치 처리 간격과 동시성 수준에 따른 데이터 적재 성능:
| 배치 처리 간격(s) | 데이터 적재 동시성 | 버킷 수 | 처리량(행/s) | 엔드투엔드 평균 지연 시간(s) | 엔드투엔드 P99 지연 시간(s) |
|---|---|---|---|---|---|
| 0.2 | 1 | 32 | 6073 | 0.211 | 0.517 |
| 1 | 1 | 32 | 31586 | 0.71 | 1.39 |
| 10 | 1 | 32 | 67437 | 5.65 | 10.90 |
| 20 | 1 | 32 | 93769 | 10.962 | 20.682 |
| 60 | 1 | 32 | 125000 | 32.46 | 62.17 |
| 0.2 | 10 | 32 | 9300 | 0.38 | 0.704 |
| 1 | 10 | 32 | 34633 | 0.75 | 1.47 |
| 10 | 10 | 32 | 82023 | 5.44 | 10.43 |
| 20 | 10 | 32 | 139731 | 11.12 | 22.68 |
| 60 | 10 | 32 | 171642 | 32.37 | 61.93 |
버킷 수가 데이터 적재 성능에 미치는 영향:
| 배치 처리 간격(s) | 데이터 적재 동시성 | 버킷 수 | 처리량(행/s) | 엔드투엔드 평균 지연 시간(s) | 엔드투엔드 P99 지연 시간(s) |
|---|---|---|---|---|---|
| 1 | 10 | 4 | 34722 | 0.86 | 2.28 |
| 1 | 10 | 16 | 34526 | 0.8 | 1.52 |
| 1 | 10 | 32 | 34633 | 0.75 | 1.47 |
| 1 | 10 | 64 | 34829 | 0.81 | 1.51 |
| 1 | 10 | 128 | 34722 | 0.83 | 1.55 |
Group Commit 테스트
빈번한 소규모 배치 데이터 적재에는 Group Commit을 활성화하는 것이 권장되며, 이를 통해 데이터 적재 성능을 크게 높일 수 있습니다. Group Commit 성능 테스트 데이터는 Group Commit 성능을 참조하세요.
자주 묻는 질문
Q1: 적절한 데이터 적재 방식은 어떻게 선택하나요?
데이터 소스와 실시간 요구 사항에 따라 선택하세요. 로컬 파일의 실시간 푸시에는 Stream Load, HDFS/S3의 대규모 배치에는 Broker Load, Kafka의 스트리밍 데이터에는 Routine Load, 외부 테이블 또는 Doris 테이블 간 ETL에는 Insert Into / Select, MySQL 호환 시나리오에는 MySQL Load를 사용하세요.
Q2: 빈번한 소규모 배치 데이터 적재가 성능에 큰 영향을 주는 이유는 무엇인가요?
빈번한 소량 데이터 적재는 Doris에서 Compaction을 자주 수행하게 하여 심각한 쓰기 증폭을 일으킵니다. 클라이언트에 데이터를 수 MB에서 수 GB까지 모으거나, Group Commit을 활성화하여 서버 측에서 배치 처리하세요.
Q3: 데이터 적재 시 작은 파일이 많이 생성되고 Compaction 부담이 높으면 어떻게 해야 하나요?
Group Commit을 활성화하여 작은 트랜잭션을 병합하거나, 클라이언트에 데이터를 수백 MB에서 수 GB까지 모은 후 적재하세요. 동시에 파티셔닝 및 버킷팅 설계를 검토하여 활성 Tablet이 과도하게 늘어나지 않도록 하세요.
Q4: 한 번의 데이터 적재에 너무 많은 파티션을 포함하면 안 되는 이유는 무엇인가요?
각 Tablet은 메모리에 활성 Memtable 하나를 유지합니다. 활성 Memtables가 차지하는 총 메모리가 너무 많아지면 OOM을 방지하기 위해 조기 flush가 발생하며, 이로 인해 작은 파일이 많이 생성되어 데이터 적재 성능이 저하됩니다. 한 번의 데이터 적재에 포함되는 파티션 수를 제한하면 이 문제를 완화할 수 있습니다.
Q5: 데이터 적재당 데이터양은 클수록 좋은가요?
아닙니다. 각 배치를 100 GB 이하로 유지하세요. 배치가 지나치게 크면 재시도 비용과 BE 메모리 및 디스크에 미치는 영향이 커집니다. 대용량 로컬 파일에는 자동 배치 처리를 지원하는 streamloader 도구를 사용할 수 있습니다.
Q6: Tablet 크기로 1-10 GB를 권장하는 이유는 무엇인가요?
Tablet이 너무 작으면 집계 효과가 낮아지고 메타데이터 관리 부담이 커지며, 너무 크면 마이그레이션과 보충 비용이 높아집니다. 1-10 GB는 데이터 적재, 쿼리, 복제본 관리 간 균형을 이루는 경험적 범위입니다.
Q7: Stream Load 동시성은 어떻게 설정해야 하나요?
단일 BE의 Stream Load 동시성은 128을 초과하지 않아야 하며(webserver_num_workers로 제한), 반드시 512 미만이어야 합니다(doris_max_remote_scanner_thread_pool_thread_num으로 제한). 그렇지 않으면 BE 프로세스가 응답하지 않을 수 있습니다.
Q8: MemTable forwarding은 어떤 시나리오에서 적용되나요?
스토리지와 컴퓨팅이 통합된 배포 모드의 INSERT INTO...SELECT에만 적용됩니다. 단일 복제본의 데이터 적재 시간은 기존의 36%로, 복제본이 세 개인 경우에는 54%로 줄어듭니다. 컴퓨팅과 스토리지가 분리된 모드에서는 현재 이 최적화를 지원하지 않습니다.
Q9: 데이터 쏠림은 어떻게 방지하나요?
적절한 버킷 수를 설정하고(압축 후 단일 Tablet 크기 1-10 GB), 적절한 버킷 키를 선택하세요. 랜덤 버킷팅 시나리오에서는 load_to_single_tablet=true를 활성화하여 분산 오버헤드를 줄일 수 있습니다.
문제 해결
| 증상 | 가능한 원인 | 조사 및 해결 방법 |
|---|---|---|
| 낮은 데이터 적재 처리량, 잦은 Compaction | 빈번한 소규모 배치 데이터 적재로 인한 쓰기 증폭 | 클라이언트 측에서 배치 처리하거나 Group Commit 활성화 |
| 데이터 적재 중 작은 파일이 많이 생성됨 | 한 번의 데이터 적재에 너무 많은 파티션이 포함되어 Memtable 조기 flush 발생 | 데이터 적재당 파티션 수를 줄이고 파티션을 순서대로 적재 |
| 적재한 데이터를 조회할 수 있게 되기까지 지연이 큼 | 쓰기를 완료한 복제본이 과반수에 도달하지 못함, 느린 Publish | SHOW LOAD로 작업 상태 확인, BE 상태 점검 및 필요시 게시 시간 제한 증가 |
| BE OOM 또는 잦은 Flush | 동시에 활성화된 파티션/Tablet이 너무 많음, MemTables 분산 | 파티션을 순서대로 적재, 버킷 수 축소, 동시성 감소 |
| FE Edit Log 부담이 높음 | 빈번한 소규모 배치 데이터 적재, 과도한 트랜잭션 수 | Group Commit 활성화 또는 클라이언트 측 배치 처리, 동시성이 너무 높은지 검토 |
| Compaction이 처리 속도를 따라가지 못하고 쿼리가 느려짐 | 작은 파일이 너무 많음, 심각한 쓰기 증폭 | 데이터 적재당 데이터양 증가, 버킷팅 튜닝, 필요시 Compaction 매개변수 조정 |
| 컴퓨팅과 스토리지가 분리된 환경에서 데이터 적재 성능 변동 | 객체 스토리지의 QPS 제한 | 동시성 제어, 배치당 데이터양 증가, 객체 스토리지 측 QPS 할당량 확인 |
| 데이터 적재에서 오류 행 보고 | 데이터 형식 불일치, 컬럼 매핑 오류 | 반환된 ErrorURL로 오류 샘플 확인, 컬럼 매핑·구분자·오류 허용 범위 조정 |
| BE 프로세스가 응답하지 않음 | 단일 BE의 Stream Load 동시성이 512 초과 | 동시성 감소, doris_max_remote_scanner_thread_pool_thread_num 조정 |
| 웹 서버 스레드 고갈, 느린 Stream Load | 단일 BE의 동시성이 128 초과 | 동시성을 128 미만으로 유지하거나 webserver_num_workers 조정 |
| 낮은 Broker Load 동시성 | 단일 압축 / Parquet / ORC 파일이 너무 크고 분할되지 않음 | 데이터 적재 전에 큰 파일을 여러 작은 파일로 분할 |
| 단일 Broker Load 실패 시 재시도 비용이 높음 | 배치 크기가 너무 큼 | 각 배치를 100 GB 미만으로 유지하고 배치로 나누어 제출 |