반응형
1. Apache Doris 기술이란?
왜 필요한가 — 기존 방식의 한계
실무에서 분석 파이프라인을 굴려 본 사람이라면 다음 패턴을 익숙하게 마주합니다.
- ClickHouse의 분산 JOIN 한계 — 단일 노드 성능은 무시무시하지만, 큰 팩트 테이블끼리 분산 JOIN을 던지면 Distributed 테이블의 GLOBAL JOIN이 폭주하거나, Colocate 키를 미리 못 맞춰서 데이터 셔플로 무너짐
- Hive/Trino 스택의 분 단위 지연 — Hive Metastore + Trino + S3 조합은 강력하지만, 데이터가 "지금 막 들어왔는데 1초 안에 보고 싶다"는 요구를 만족시키기 어려움
- Snowflake/BigQuery의 단가 — 잘 만들어진 SaaS지만, 대시보드 한 장이 분당 수백 번 갱신되는 운영 환경에서는 크레딧/쿼리 단가가 빠르게 누적
- Lambda 아키텍처의 복잡성 — 실시간(Kafka→Flink→OLAP) + 배치(S3→Spark→OLAP)를 따로 굴리면, 두 결과가 미세하게 안 맞아 디버깅에 일주일이 사라짐
- 차원/사실 모델링 강요 — 분석 워크로드가 다양해지는데, 컬럼 OLAP은 사전 집계와 비정규화가 강제되어 모델 변경 시 ETL 폭탄
기술 정의
Apache Doris는 Baidu에서 출발해 ASF Top-Level 프로젝트로 자리 잡은 오픈소스 실시간 MPP 분석 데이터베이스입니다. 표준 MySQL 프로토콜을 그대로 쓰면서, 내부적으로는 FE(Java, 메타데이터/플래너)와 BE(C++, 저장/실행)가 분리된 진짜 MPP 구조를 갖습니다. Aggregate / Unique / Duplicate 세 가지 데이터 모델, 비동기 머터리얼라이즈드 뷰 + 자동 쿼리 재작성, 벡터화 파이프라인 실행 엔진, Iceberg/Hudi/Hive 다중 카탈로그를 한 바이너리에 모아둔 것이 Doris의 정체성입니다.
핵심 한 줄 정의
Apache Doris = MySQL 프로토콜 호환 MPP OLAP DB. FE/BE 분리, 벡터화 파이프라인 실행, 비동기 MV 자동 재작성, 멀티 카탈로그 페더레이션을 한 클러스터에 통합.
Apache Doris = MySQL 프로토콜 호환 MPP OLAP DB. FE/BE 분리, 벡터화 파이프라인 실행, 비동기 MV 자동 재작성, 멀티 카탈로그 페더레이션을 한 클러스터에 통합.
2. Apache Doris 기술 특징
| 특징 | 설명 |
| True MPP | FE가 분산 실행 플랜을 만들고 BE들이 병렬로 처리. 분산 Hash/Broadcast/Bucket Shuffle JOIN 모두 지원. |
| Pipeline Execution | 2.x부터 도입된 비동기 파이프라인 실행 엔진. CPU 코어를 풀로 활용, 동시성 폭주에도 안정적. |
| Vectorized Engine | SIMD 기반 컬럼 벡터 처리. 행 단위 처리 대비 5~10배 처리량. |
| 3가지 데이터 모델 | Aggregate(사전 집계), Unique(Primary Key, Upsert), Duplicate(원본 보존). 워크로드별 선택 가능. |
| Async Materialized View | 2.1+ 비동기 MV. 옵티마이저가 SQL을 자동 재작성해 MV로 라우팅. dbt와 결합 자연스러움. |
| Multi-Catalog | Iceberg, Hudi, Paimon, Hive, JDBC, Elasticsearch를 외부 카탈로그로 마운트해 페더레이션 쿼리. |
| Storage-Compute Decoupling | 3.x의 Compute Group 모드. S3/오브젝트 스토리지에 데이터 두고 BE를 워크로드별 그룹으로 분리. |
| MySQL Protocol | MySQL 클라이언트/JDBC/ORM 그대로 사용. BI 툴(Superset, Tableau, Metabase) 즉시 연결. |
| Stream Load / Routine Load | HTTP PUT 기반 마이크로 배치 ingest, Kafka 직결 Routine Load. 별도 ETL 미들웨어 없이 실시간 적재. |
| Workload Group | CPU/메모리/IO 쿼터를 그룹별로 격리. 무거운 ETL이 BI 대시보드를 죽이는 사고 방지. |
3. Apache Doris 동작방식
ⅰ. 구성 요소
| 컴포넌트 | 언어 | 역할 |
| FE (Frontend) | Java | 메타데이터 관리(BDB-JE 기반 Raft-like), SQL 파싱/플래닝/옵티마이저(Nereids), MySQL 프로토콜 게이트웨이. Master / Follower / Observer 역할. |
| BE (Backend) | C++ | 실제 데이터 저장(Tablet 단위 컬럼 저장), 쿼리 실행, Compaction, 데이터 적재. |
| Tablet / Replica | — | 테이블은 Partition → Bucket → Tablet으로 쪼개짐. Tablet은 보통 3 Replica로 BE에 분산 저장. |
| Nereids Planner | Java | 2.x부터 기본 채택된 새 코스트 기반 옵티마이저. CBO + 룰 기반 + MV 재작성 통합. |
| Pipeline Engine | C++ | BE 내부의 비동기 실행 엔진. Operator를 파이프라인으로 묶어 코어 활용 극대화. |
| CN (Compute Node) | C++ | 3.x 분리형 모드의 무상태 실행 노드. 데이터는 S3에, 캐시는 로컬에. 탄력적 스케일. |
| Broker | Java | HDFS/S3 등 원격 스토리지 접근용 보조 데몬. Broker Load와 백업/복원에서 사용. |
ⅱ. 데이터 흐름 — 쓰기 경로 (Stream Load)
- 클라이언트가 HTTP PUT으로 FE에 batch를 보냄 (CSV/JSON/Parquet)
- FE가 적재 트랜잭션 ID를 발급하고 적절한 BE를 Coordinator로 지정해 redirect
- Coordinator BE가 데이터를 파싱 → 각 Tablet의 리더 Replica에 분배 (Hash by Bucket Key)
- 각 BE가 메모리 MemTable에 누적 → flush 시 RowSet(컬럼 파일 묶음)으로 디스크 기록
- 3개 Replica 중 정족수(Quorum, 기본 2/3) 성공하면 Publish → 가시성 확보
- 백그라운드에서 Compaction이 작은 RowSet들을 큰 단위로 병합
ⅲ. 데이터 흐름 — 읽기 경로 (SELECT)
- MySQL 프로토콜로 FE에 SQL 도착
- Nereids 파서 → 분석 → 룰 기반 변환(컬럼 프루닝, 술어 푸시다운, MV 재작성) → CBO로 분산 플랜 결정
- FE가 BE 단편(Fragment)을 만들어 각 BE에 송신 → BE의 Pipeline Engine이 병렬 실행
- BE 간 셔플(Hash Exchange)이 필요한 단계는 Brpc로 데이터 교환
- 최종 결과는 Coordinator BE에 모이고 FE를 거쳐 클라이언트로 스트리밍
4. Apache Doris 구성 및 흐름도
ⅰ. 전체 구성도
┌───────────────────────────────────────────────────────────────┐
│ Clients: BI Tools / JDBC / MySQL CLI / curl(Stream Load) │
└──────────────────────────┬────────────────────────────────────┘
│ MySQL Protocol :9030 / HTTP :8030
▼
┌───────────────────────────────────────────────────────┐
│ FE Cluster (Java) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Master │◄►│ Follower │◄►│ Follower │ Observer │
│ └──────────┘ └──────────┘ └──────────┘ │
│ - Metadata (BDB-JE Raft-like) │
│ - Nereids Planner / CBO / MV Rewrite │
│ - Catalog Manager (Internal + Iceberg/Hive/JDBC) │
└─────────────────────────┬─────────────────────────────┘
│ Brpc Fragment Dispatch
┌────────────────┼────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ BE 1 │ │ BE 2 │ │ BE 3 │
│ (C++) │◄───►│ (C++) │◄───►│ (C++) │
│ Pipeline │ │ Pipeline │ │ Pipeline │
│ Engine │ │ Engine │ │ Engine │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ Tablets │ Tablets │ Tablets
▼ ▼ ▼
┌─────────────────────────────────────────────┐
│ Local Storage (Segment files, Columnar) │
│ or Object Storage (S3/HDFS) [3.x 분리형] │
└─────────────────────────────────────────────┘
ⅱ. 단계별 설명
| 단계 | 처리 내용 |
| ① 접속 | MySQL 클라이언트 또는 JDBC가 FE의 9030 포트(MySQL 프로토콜)로 연결. 인증/세션 변수 처리. |
| ② 플래닝 | Nereids가 SQL → AST → Logical Plan → Optimized Plan → Physical Plan을 만든 뒤, MV 재작성/Runtime Filter 삽입을 적용. |
| ③ 분배 | Plan을 Fragment로 쪼개 각 BE에 Brpc로 전송. Coordinator BE가 결정됨. |
| ④ 실행 | BE의 Pipeline Engine이 Operator를 파이프라인으로 연결해 SIMD 벡터 단위로 실행. 필요한 Tablet은 로컬 또는 S3 캐시에서 읽음. |
| ⑤ 셔플/조인 | 분산 JOIN/집계 시 Hash Exchange로 BE 간 데이터 재분배. Colocate JOIN이면 셔플 생략. |
| ⑥ 집계/반환 | Final aggregation 후 Coordinator BE → FE → 클라이언트로 결과 스트리밍. |
ⅲ. 실제 처리 흐름 — Kafka 실시간 적재 + BI 대시보드
[App] ─► [Kafka topic: events] ─► [Doris Routine Load Job]
│
▼ Stream Load 내부 변환
[BE Coordinator]
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
[BE1 Tablet1] [BE2 Tablet2] [BE3 Tablet3]
│ │ │
▼ ▼ ▼
MemTable Flush ──► RowSet ──► Compaction ──► Sorted Segment
│
┌──────────────────┴──────────────────┐
▼ ▼
[Async MV: events_daily_agg] [Base Table: events]
│ │
└────────────┬────────────────────────┘
▼
[Superset / Metabase / Tableau]
▼
사용자 대시보드 (1~5초 지연)
5. Apache Doris 설치 방법
ⅰ. 최소 권장 사양
| 항목 | PoC | 프로덕션 (수십 TB) |
| FE 노드 | 1개 (4C/8G) | 3개 (8C/16G, 1 Master + 2 Follower) 홀수개 필수 |
| BE 노드 | 3개 (8C/16G, NVMe 200GB) | ≥5개 (16C/64G, NVMe 2TB+, 별도 데이터 디스크) |
| OS | CentOS 7+/RHEL 8+/Ubuntu 22.04 | RHEL 8+/Ubuntu 22.04 LTS, 커널 4.18+ |
| JVM (FE) | OpenJDK 17 (필수) | OpenJDK 17, ZGC 권장, Heap ≥ 8GB |
| 네트워크 | 1GbE | 10GbE 이상, 셔플 트래픽 큼 |
ⅱ. 바이너리 설치 (단일 노드 PoC)
# 1) 커널 파라미터 — 누락하면 BE가 OOM/ENOMEM으로 죽습니다
sudo sysctl -w vm.max_map_count=2000000
sudo sysctl -w vm.swappiness=0
ulimit -n 655350
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
# 2) JDK 17 설치 (FE 필수)
sudo apt install -y openjdk-17-jdk
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
# 3) Doris 바이너리 다운로드 (예: 3.0.x)
wget https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-3.0.x-bin-x64.tar.gz
tar -xzf apache-doris-3.0.x-bin-x64.tar.gz && cd apache-doris-3.0.x-bin-x64
# 4) FE 기동
cd fe && bin/start_fe.sh --daemon
# FE 메타 디렉터리, edit_log_port=9010, query_port=9030 설정 필요
# 5) BE 기동
cd ../be && bin/start_be.sh --daemon
# 6) BE를 클러스터에 등록
mysql -h127.0.0.1 -P9030 -uroot -e "ALTER SYSTEM ADD BACKEND '127.0.0.1:9050';"
mysql -h127.0.0.1 -P9030 -uroot -e "SHOW BACKENDS\G"
ⅲ. Docker Compose / Kubernetes
테스트는 공식 Docker Compose 예제로 5분이면 충분합니다. 운영은 Doris Operator(공식 K8s 오퍼레이터)를 통해 DorisCluster CR로 선언하고, BE는 StatefulSet + Persistent Volume(NVMe 클래스)로 띄우는 것이 표준입니다. FE는 헤드리스 서비스 + 3개 Pod 홀수 구성, BE는 anti-affinity로 노드 분산이 필수입니다.
설치 시 흔한 실수 — 직접 겪은 케이스
- FE 짝수 구성 — Follower를 2개로 두면 Master 선출이 한쪽 장애에 막힘. 반드시 1·3·5 홀수.
- BE의 max_map_count 누락 — 로그에 mmap failed이 떨어지며 OOM처럼 보이지만 실제 원인은 vm.max_map_count.
- Swap 활성화 상태로 BE 기동 — 컴팩션 중 시스템이 Swap에 데이터를 쓰며 latency가 100배 튐. swappiness=0 필수.
- JDK 11 사용 — Doris 2.1+는 JDK 17 강제. 11로 띄우면 FE가 silent fail.
6. Apache Doris 사용 방법
ⅰ. 테이블 만들기 — 데이터 모델 선택
-- 1) 이벤트 원본을 그대로 저장 (Duplicate 모델)
CREATE TABLE events (
event_time DATETIME NOT NULL,
user_id BIGINT,
event_type VARCHAR(64),
revenue DECIMAL(18,4),
payload JSONB
)
DUPLICATE KEY(event_time, user_id)
PARTITION BY RANGE(event_time) ()
DISTRIBUTED BY HASH(user_id) BUCKETS 32
PROPERTIES (
"replication_num" = "3",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-30",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix"= "p",
"dynamic_partition.buckets" = "32"
);
-- 2) Upsert가 필요한 사용자 프로필 (Unique Key 모델, MoW 권장)
CREATE TABLE user_profile (
user_id BIGINT,
nickname VARCHAR(64),
tier VARCHAR(16),
last_login DATETIME
)
UNIQUE KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 16
PROPERTIES (
"replication_num" = "3",
"enable_unique_key_merge_on_write" = "true"
);
ⅱ. 실시간 적재 — Stream Load
# HTTP PUT 한 줄로 실시간 적재
curl --location-trusted -u admin:secret \
-H "label:events_$(date +%s)" \
-H "format:json" -H "strip_outer_array:true" \
-T events_batch.json \
http://fe-host:8030/api/mydb/events/_stream_load
ⅲ. Kafka 직결 — Routine Load
CREATE ROUTINE LOAD mydb.kafka_events ON events
COLUMNS(event_time, user_id, event_type, revenue, payload)
PROPERTIES (
"desired_concurrent_number" = "6",
"max_batch_interval" = "10",
"max_batch_rows" = "200000",
"format" = "json",
"strip_outer_array" = "true"
)
FROM KAFKA (
"kafka_broker_list" = "kafka1:9092,kafka2:9092",
"kafka_topic" = "events",
"property.group.id" = "doris-events",
"property.kafka_default_offsets" = "OFFSET_END"
);
ⅳ. 비동기 머터리얼라이즈드 뷰 — 자동 재작성
CREATE MATERIALIZED VIEW events_daily_agg
BUILD IMMEDIATE REFRESH AUTO ON SCHEDULE EVERY 5 MINUTE
DISTRIBUTED BY HASH(d) BUCKETS 8
PROPERTIES ("replication_num" = "3")
AS
SELECT date_trunc(event_time, 'day') AS d,
event_type,
count(*) AS cnt,
sum(revenue) AS revenue_sum
FROM events
GROUP BY 1, 2;
-- 사용자는 base table을 그대로 조회. Optimizer가 events_daily_agg로 자동 라우팅.
SET enable_materialized_view_rewrite = true;
SELECT date_trunc(event_time,'day'), event_type, sum(revenue)
FROM events
WHERE event_time >= '2026-04-01'
GROUP BY 1, 2;
ⅴ. 멀티 카탈로그 — Iceberg 페더레이션
CREATE CATALOG iceberg_lakehouse PROPERTIES (
"type" = "iceberg",
"iceberg.catalog.type" = "rest",
"uri" = "http://lakekeeper:8181/catalog",
"warehouse" = "s3://lake/warehouse",
"s3.endpoint" = "https://s3.ap-northeast-2.amazonaws.com",
"s3.access_key" = "AKIA...",
"s3.secret_key" = "..."
);
SELECT i.product_id, sum(e.revenue)
FROM internal.mydb.events e
JOIN iceberg_lakehouse.gold.products i USING (product_id)
GROUP BY 1 ORDER BY 2 DESC LIMIT 100;
ⅵ. 운영 시 고려사항
| 항목 | 권장 |
| Bucket 수 | 파티션당 데이터 1~10GB가 한 Tablet 크기에 맞도록 설정. 너무 적으면 핫스팟, 너무 많으면 메타 폭증. |
| Replica | 프로덕션은 항상 3. 1로 두면 BE 한 대만 죽어도 쿼리가 깨짐. |
| Compaction | Routine Load 부하가 높으면 compaction_task_num_per_disk를 6~8로 상향, 그래도 누적되면 적재 batch 크기를 키우는 게 근본. |
| Workload Group | 최소 etl, bi 두 그룹으로 분리. ETL이 BI 동시성을 잡아먹는 사고 방지. |
| Backup | S3 백업(BACKUP SNAPSHOT)을 일 단위 + CCR(2.x+)로 DR 사이트 복제. |
7. Apache Doris 자주 쓰는 명령어
ⅰ. 클러스터 상태 확인
-- FE/BE 노드 헬스체크
SHOW FRONTENDS\G
SHOW BACKENDS\G
-- Tablet 분포 / 누락 / 비정상 Replica
ADMIN SHOW REPLICA STATUS FROM mydb.events;
SHOW TABLET FROM mydb.events;
ADMIN CHECK TABLET (10001, 10002) PROPERTIES("type"="consistency");
-- 진행 중인 적재/쿼리
SHOW LOAD ORDER BY CreateTime DESC LIMIT 20;
SHOW ROUTINE LOAD\G
SHOW PROC '/current_queries';
SHOW PROC '/cluster_balance';
ⅱ. 성능 진단
-- 실행 계획 (CBO 결정 확인)
EXPLAIN VERBOSE SELECT ...;
-- 실행 후 프로파일 — 어떤 Operator가 느린지
SET enable_profile = true;
SELECT ... ;
SHOW QUERY PROFILE "/";
-- Compaction 점수 (높으면 쌓여있다는 뜻)
SHOW PROC '/cluster_balance/cluster_load_stat/location_default';
-- 실행 계획 (CBO 결정 확인)
EXPLAIN VERBOSE SELECT ...;
-- 실행 후 프로파일 — 어떤 Operator가 느린지
SET enable_profile = true;
SELECT ... ;
SHOW QUERY PROFILE "/";
-- Compaction 점수 (높으면 쌓여있다는 뜻)
SHOW PROC '/cluster_balance/cluster_load_stat/location_default';
ⅲ. 사용자/권한/워크로드
# 1) 커널 파라미터 — 누락하면 BE가 OOM/ENOMEM으로 죽습니다
sudo sysctl -w vm.max_map_count=2000000
sudo sysctl -w vm.swappiness=0
ulimit -n 655350
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
# 2) JDK 17 설치 (FE 필수)
sudo apt install -y openjdk-17-jdk
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
# 3) Doris 바이너리 다운로드 (예: 3.0.x)
wget https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-3.0.x-bin-x64.tar.gz
tar -xzf apache-doris-3.0.x-bin-x64.tar.gz && cd apache-doris-3.0.x-bin-x64
# 4) FE 기동
cd fe && bin/start_fe.sh --daemon
# FE 메타 디렉터리, edit_log_port=9010, query_port=9030 설정 필요
# 5) BE 기동
cd ../be && bin/start_be.sh --daemon
# 6) BE를 클러스터에 등록
mysql -h127.0.0.1 -P9030 -uroot -e "ALTER SYSTEM ADD BACKEND '127.0.0.1:9050';"
mysql -h127.0.0.1 -P9030 -uroot -e "SHOW BACKENDS\G"
CREATE USER bi_reader IDENTIFIED BY 'XXXXXXXX';
GRANT SELECT_PRIV ON mydb.* TO bi_reader;
-- 워크로드 그룹 격리
CREATE WORKLOAD GROUP bi
PROPERTIES ("cpu_share"="40","memory_limit"="40%","max_concurrency"="100");
SET PROPERTY FOR 'bi_reader' 'default_workload_group'='bi';
ⅳ. 실전 트러블슈팅
| 증상 | 원인 | 해결 |
| BE OOM 반복 | 대형 GROUP BY/JOIN이 메모리 한계 초과. exec_mem_limit 기본 2GB는 운영용으로 너무 작음. | 세션 변수로 상향 + 디스크 스필 활성화(enable_spill=true). 워크로드 그룹별 메모리 쿼터로 한 쿼리가 BE 전체를 잡아먹지 않게 격리. |
| Routine Load lag 폭증 | batch 간격(max_batch_interval)이 너무 짧아 Compaction이 따라오지 못함. 작은 RowSet 폭증. | batch 간격을 10~30초로 늘리고 행 수도 확대. SHOW PROC '/cluster_balance'로 Compaction 점수 모니터링. |
| 분산 JOIN이 느림 | 두 큰 테이블이 같은 키로 분산되지 않아 매번 셔플 발생. | Colocate Group을 묶어 같은 BE에 같은 Bucket을 위치시킴. 또는 작은 차원 테이블이면 Broadcast JOIN 힌트 사용. |
| MV 재작성 안 됨 | 쿼리 술어/조인/그룹키가 MV 정의보다 더 좁거나 다름. CBO가 매칭 못 함. | EXPLAIN MEMO PLAN로 매칭 실패 이유 확인. MV를 더 일반화하거나 쿼리 술어를 MV 범위 안으로 조정. |
| FE Master 선출 실패 | Follower 짝수 + 동시 장애. BDB-JE 정족수 미달. | FE는 항상 홀수. 응급 시 metadata_failure_recovery=true로 단일 노드 복구 후 재구성. |
| 타임존 결과 어긋남 | FE 세션, BE OS, 클라이언트 세 곳의 TZ가 달라 DATETIME 결과가 +9시간 밀림. | FE의 time_zone='Asia/Seoul' 글로벌 변수, BE OS TZ, JDBC URL serverTimezone 셋을 일치. |
| Tablet Unhealthy 다수 | BE 다운/디스크 풀. 복제본 부족. | ADMIN REPAIR TABLE 또는 BE 디스크 회수. 자동 균형(Tablet Scheduler)이 동작하도록 disable_balance=false 확인. |
| Iceberg 카탈로그 stale | 외부 엔진(Spark/Flink)이 새 스냅샷을 만들었지만 Doris의 메타 캐시가 갱신 안 됨. | REFRESH CATALOG iceberg_lakehouse; 또는 카탈로그 file.meta.cache.ttl-second을 짧게. |
8. Apache Doris 활용방안
ⅰ. 대표 적용 사례
| 사례 | 내용 |
| 리얼타임 BI | Kafka → Routine Load → Doris → Superset/Tableau. 1~5초 지연으로 어제 KPI가 아니라 "지금 KPI"를 보여줌. |
| 고객 사용 분석 | 행위 이벤트 + 사용자 프로필을 분산 JOIN해 코호트 분석/퍼널 분석. ClickHouse에서는 까다로운 워크로드. |
| 레이크하우스 가속 | Iceberg/Hudi 위 데이터를 Doris가 바로 쿼리. 핫 데이터만 내부 테이블로 캐시해 대시보드 응답 1초 이내. |
| 광고/추천 피처스토어 | Unique Key + MoW로 사용자 피처 Upsert, 서빙단에서 단건 lookup + 집계 동시. |
| 로그/관측성 OLAP | Inverted Index + Bloom Filter로 로그 검색. ELK 비용 절감 + SQL 인터페이스. |
ⅱ. 대안 기술과의 비교
| 기준 | Apache Doris | ClickHouse | StarRocks | Snowflake |
| 아키텍처 | FE/BE MPP | 단일 노드 강함, 분산은 Distributed 테이블 | Doris 포크, FE/BE 유사 | SaaS, 분리형 |
| 분산 JOIN | 강함 (Colocate, Bucket Shuffle, Broadcast) | 제한적 (GLOBAL JOIN 비용 큼) | 강함 (Doris와 동급) | 매우 강함 |
| 실시간 ingest | Stream/Routine Load 내장 | Kafka Engine, 다소 까다로움 | Routine Load 내장 | Snowpipe (분 단위) |
| 비동기 MV | 자동 재작성 지원 | 제한적 MV (자동 재작성 약함) | 자동 재작성 지원 | Dynamic Tables |
| 운영 모델 | 셀프호스팅, K8s 오퍼레이터 | 셀프호스팅, ClickHouse Cloud | 셀프호스팅, CelerData Cloud | 완전 SaaS |
| 비용 | 하드웨어 비용만 | 하드웨어 비용만 | 하드웨어 비용만 | 크레딧 단가 높음 |
| 적합도 | 실시간 + JOIN + MV가 모두 필요할 때 | 사전 모델링된 시계열/이벤트 | Doris와 유사, 일부 기능 우위 | 대규모 엔터프라이즈 DW |
ⅲ. 언제 쓰면 안 되는가
- OLTP 워크로드 — 단건 INSERT/UPDATE가 초당 수만 건 들어오는 시스템에는 부적합. 트랜잭션 격리가 OLTP 수준이 아님. 이 경우 PostgreSQL/MySQL/TiDB 사용.
- 다중 행 트랜잭션 — 다수 테이블에 걸친 ACID 트랜잭션이 필요하면 Doris의 보장 수준은 부족. 일반 RDB로.
- 풀텍스트 검색 메인 엔진 — Inverted Index가 있지만 OpenSearch/Elasticsearch 수준의 랭킹/한국어 형태소 분석은 약함. 단순 로그 검색 정도까지.
- 초대형 단발성 ETL — 페타바이트급 ad-hoc 배치 변환은 Spark/Trino + Iceberg가 더 자연스러움. Doris는 자주 도는 분석에 강점.
- 벡터 검색 메인 엔진 — 벡터 인덱스 기능이 있지만 Qdrant/Milvus처럼 RAG 전용 엔진의 latency/필터링/HNSW 튜닝 자유도에는 미치지 못함.
ⅳ. 트레이드오프 정리
| 얻는 것 | 대신 감수해야 하는 것 |
| 강력한 분산 JOIN과 표준 SQL | 단일 노드 ClickHouse 대비 단순 단건 쿼리는 살짝 느림 |
| 실시간 ingest + 자동 MV 재작성 | Routine Load + Compaction 튜닝 학습 곡선 |
| 멀티 카탈로그 페더레이션 | 외부 카탈로그 메타 캐시 운영 부담 |
| 셀프호스팅으로 비용 통제 | Snowflake처럼 자동 스케일링/관리는 없음 (오퍼레이터 운영 필요) |
| MySQL 프로토콜로 BI 즉시 연결 | MySQL이 아니므로 일부 SQL 방언/함수는 미지원 |
반응형
'빅데이터(Big Data)' 카테고리의 다른 글
| AI 시대 필수 데이터 분석 기법 3가지 : 클러스터링, 필터링, 이상치 탐지 (0) | 2026.07.28 |
|---|---|
| 데이터 가치평가 3가지 방법과 데이터 자산화 핵심 요소 (1) | 2026.07.23 |
| Iceberg·Hudi·Delta 분열을 끝낸 메타데이터 변환기, Apache XTable (0) | 2026.06.29 |
| 실시간 업데이트가 가능한 데이터 레이크하우스의 표준, Apache Hudi 분석 (0) | 2026.05.13 |
| 데이터 레이크의 표준 페더레이션 SQL 쿼리 엔진, Trino 분석 (0) | 2026.05.12 |