변경 로그 / Table Stream
요약 Apache Doris Table Stream은 MySQL binlog을 읽듯 Doris 테이블의 행 수준 변경 사항(삽입, 업데이트, 삭제)을 읽을 수 있게 하는 공개 API로 출시될 예정입니다. 기반 구현은 이미 코드베이스에 있습니다. 테이블별 changelog, 파티션별 오프셋을 고정하는
STREAM객체, 소비 메타데이터가 포함됩니다. 이 기능은 아직 GA가 아니며,changelog.ttl_seconds의 기본값은 86,400초(하루)입니다. Doris에서 변경 데이터를 추출하는 일반적인 CDC에는 Flink Doris Connector를 사용하세요. 상태: 출시 예정(프리뷰).

여기서 설명하는 STREAM 객체, changelog.enable 테이블 속성, 소비 메타데이터 뷰는 Doris 소스 트리에 있지만 아직 안정적인 사용자용 API로 출시되지 않았습니다. GA 전에 구문과 동작이 바뀔 수 있습니다. 현재 프로덕션 CDC 파이프라인에는 Kafka 및 CDC 통합을 사용하세요.
Apache Doris에서 changelog와 Table Stream을 사용하는 이유는 무엇인가요?
Apache Doris changelog와 Table Stream은 다운스트림 소비자에게 행 수준 변경 피드를 제공합니다. 따라서 Flink 작업, 감사 추적 시스템, 검색 인덱스가 테이블을 다시 읽지 않고도 모든 삽입, 업데이트, 삭제에 반응할 수 있습니다. Apache Doris는 변경 데이터 수집에 강점이 있습니다. 하지만 변경 데이터를 다시 내보내기는 더 어렵습니다. 다운스트림 시스템(Flink 작업, 감사 추적 시스템, 다른 Doris 클러스터, 검색 인덱스)이 모든 삽입, 업데이트, 삭제에 반응해야 한다면 현재 선택지는 번거롭습니다.
- 주기적으로 테이블을 다시 읽고 차이를 비교합니다. 구현은 쉽지만 실행 비용이 높고 실시간으로 동작하지 않습니다.
- 데이터 생산자가 Kafka와 Doris에 이중으로 기록합니다. 기록 대상도 두 곳이고 장애가 발생할 수 있는 지점도 두 곳입니다.
Changelog와 Table Stream은 이 문제를 해결합니다. Changelog는 커밋된 모든 변경 사항을 행 수준에서 기록합니다. Table Stream은 이 로그를 가리키는 이름 있는 커서입니다. 소비자는 스트림에 연결해 마지막 오프셋 이후의 변경 사항을 읽고 수신을 확인합니다. MySQL binlog, Snowflake Streams, Postgres 논리 복제 슬롯과 같은 개념을 Doris의 독립적인 객체로 구현한 것입니다.
Apache Doris changelog와 Table Stream은 무엇인가요?
Apache Doris changelog는 Doris가 테이블별로 유지하는 행 수준 변경 로그이고, Apache Doris Table Stream은 이를 행 수준 CDC로 노출하는 소비자용 객체입니다. Changelog는 커밋된 모든 행 변경 사항과 커밋 타임스탬프를 기록하며, 선택적으로 변경 전 값도 기록합니다. 이는 클러스터 간 복제(CCR)에 사용되는 binlog과 별개입니다. Changelog에는 자체 changelog.* 속성이 있으며, 한 테이블에서 둘 다 활성화할 수는 없습니다.
Table Stream은 changelog를 기반으로 하는 소비자용 객체입니다. 스트림은 CREATE STREAM <name> ON TABLE <base_table>로 생성하며, 소비자 한 명을 위한 파티션별 오프셋을 자체적으로 관리합니다. 또한 SHOW CREATE STREAM과 소비 진행 상황을 보여주는 information_schema 뷰를 SQL 인터페이스로 제공합니다.
주요 용어
changelog.enable: 테이블별 속성입니다.true로 설정하면 해당 테이블의 changelog가 활성화됩니다. 테이블을 생성할 때만 설정할 수 있습니다.changelog.need_historical_value: 테이블별 속성입니다.true로 설정하면 각 업데이트와 삭제 이전의 값도 기록합니다. Unique Key Merge-on-Write 테이블에서만 사용할 수 있습니다.changelog.ttl_seconds: 보존 기간 설정입니다. 기본 TTL은 하루이며, 테이블을 만든 뒤에도 변경할 수 있습니다.STREAM: 기본 테이블을 감싸고 소비자 한 명의 파티션별 오프셋을 추적하는 Doris Catalog 객체입니다.- 스트림 소비 유형:
detail,append_only,min_delta(기본값) 중 하나입니다. 스트림이 모든 행 변경 사항, 삽입만, 또는 최소 변경 집합 중 무엇을 내보낼지 결정합니다. - 스트림 지연: 파티션의 가시 버전에서 스트림에 기록된 오프셋을 뺀 값입니다.
LAG열에 표시됩니다.
Apache Doris changelog와 Table Stream은 어떻게 동작하나요?
Apache Doris changelog는 BE에서 행 수준 변경분을 기록합니다. Table Stream은 이 로그에 파티션별 오프셋을 더해 다운스트림 소비자가 변경 사항을 증분 방식으로 읽고 수신을 확인할 수 있게 합니다.
- 테이블을 만들 때 changelog를 활성화합니다.
CREATE TABLE t (...) PROPERTIES ("changelog.enable" = "true")를 사용합니다. 기존 테이블에서는 changelog를 활성화할 수 없습니다. BE는changelog.ttl_seconds에 따라 행 수준 변경분을 태블릿 데이터와 함께 보관합니다. - 테이블을 기반으로 스트림을 만듭니다.
CREATE STREAM s ON TABLE t PROPERTIES ("type" = "min_delta")를 사용합니다. FE는STREAM객체를 생성하고, 각 파티션의 현재 가시 버전을 시작 오프셋으로 설정한 뒤 데이터베이스에 등록합니다.show_initial_rows = true로 설정하면 첫 번째 읽기에서 기존 데이터가 반환되도록 동작이 바뀝니다. - 변경 사항을 소비합니다. 다운스트림 리더(현재는 외부 CDC 커넥터, 향후에는 네이티브 소비자 엔드포인트)가 스트림에서 읽습니다. 각 배치는 파티션별 오프셋을 전진시키고 소비 시각을 기록합니다.
- 오래된 변경 사항을 정리합니다. 모든 스트림이 읽었는지와 관계없이
changelog.ttl_seconds보다 오래된 변경 사항은 만료되며, 이후 백그라운드 컴팩션이 해당 저장 공간을 회수합니다. 오프셋이 보존 기간을 벗어난 스트림은 새 스냅샷을 기준으로 재설정해야 합니다. - 상태를 확인합니다.
information_schema.table_streams에는 모든 스트림과 각각의 기본 테이블이 나열됩니다.table_stream_consumption에는 파티션별UNIT(파티션),CONSUMPTION_STATUS,LAG,LAST_CONSUMPTION_TIME이 표시됩니다. 이 정보를 지연 현황을 확인하는 데 사용할 수 있습니다.
빠른 시작
-- 1. Enable the changelog when the source table is created
CREATE TABLE orders (
order_id BIGINT,
order_date DATE,
status VARCHAR(16),
amount DECIMAL(10, 2)
)
UNIQUE KEY(order_id, order_date)
PARTITION BY RANGE(order_date) (
PARTITION p_2026_05 VALUES [('2026-05-01'), ('2026-06-01'))
)
DISTRIBUTED BY HASH(order_id) BUCKETS 8
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"changelog.enable" = "true",
"changelog.need_historical_value" = "true",
"changelog.ttl_seconds" = "86400"
);
-- 2. Create a Table Stream over it (planned syntax, subject to change)
CREATE STREAM orders_cdc ON TABLE orders
PROPERTIES ("type" = "min_delta", "show_initial_rows" = "false");
-- 3. Inspect the stream and its lag
SHOW CREATE STREAM orders_cdc;
SELECT * FROM information_schema.table_stream_consumption
WHERE STREAM_NAME = 'orders_cdc';
예상 결과
+---------+------------+-----------+--------------------+-----+----------------------+
| DB_NAME | STREAM_NAME| STREAM_ID | UNIT (partition) | LAG | LAST_CONSUMPTION_TIME|
+---------+------------+-----------+--------------------+-----+----------------------+
| sales | orders_cdc | 10042 | p_2026_05 | 0 | 2026-05-09 10:14:33 |
+---------+------------+-----------+--------------------+-----+----------------------+
LAG = 0은 소비자가 파티션의 가시 버전까지 따라잡았다는 뜻입니다. 업스트림에서 쓰기 작업이 커밋되면 LAG가 증가하고, 소비자가 읽으면 감소합니다. 소비 지연이 changelog.ttl_seconds를 초과한 소비자는 새 스냅샷을 만들어야 합니다. STALE_REASON은 이 경우를 보고하지 않으므로 소비 지연 시간과 보존 기간을 비교하세요.
Apache Doris changelog와 Table Stream은 언제 사용해야 하나요?
GA 이후에는 다운스트림 시스템이 테이블 전체를 다시 읽지 않고 Doris 테이블의 행 수준 변경 이벤트를 받아야 할 때 Apache Doris changelog와 Table Stream을 사용하세요.
적합한 경우(GA 이후)
- 테이블을 다시 읽지 않고 Doris의 변경 이벤트로 다운스트림 Flink 또는 Spark 작업을 실행할 때.
- 모든 삽입과 삭제가 필요한 외부 검색 인덱스, 캐시 또는 감사 추적 시스템을 유지할 때.
- 소비자별 오프셋을 명시적으로 관리해야 하는 Doris 간 복제를 구현할 때.
- 파티션의
LAG가 바뀌면 외부 구체화된 뷰를 다시 계산하도록 트리거할 때.
적합하지 않은 경우(특히 현재)
- 현재의 프로덕션 CDC 파이프라인.
STREAM객체는 소스 트리에 있지만 GA로 발표되지 않았습니다. 대신 Kafka 및 CDC 통합을 사용하세요. - Changelog 보존 기간이 짧은데 소비자가 오랫동안 일시 중지되는 경우. 소비 지연이
changelog.ttl_seconds를 초과하면 소비자에게 아직 필요한 변경 사항이 만료되므로 데이터를 다시 채워야 합니다. - 스토리지와 컴퓨팅이 분리된 클러스터. 이 환경에서 Table Stream을 지원하는 방식은 아직 확정되지 않았습니다.
- 외부 Catalog 테이블(Hive, Iceberg)을 읽는 경우. Table Stream은 내부 OLAP 테이블만 지원합니다.
더 읽어보기
- Kafka 및 CDC 통합: 현재 변경 데이터를 Doris로 가져오고 Doris를 중심으로 이동시키는 데 지원되는 방법입니다.
- 데이터 업데이트 및 삭제: Unique Key Merge-on-Write 테이블이 행 스트림에 담길 삭제 및 순서가 뒤바뀐 업데이트를 어떻게 표현하는지 설명합니다.
- Iceberg: 복제된 테이블을 저장할 외부 대상입니다. Doris 밖으로 나가지 않고 SQL로 CDC 데이터를 Iceberg에 반영할 수 있습니다.
- Unique Key: 키당 하나의 행으로 상태를 명확하게 표현하여 다운스트림 changelog 소비자가 활용할 수 있게 하는 업스트림 테이블 모델입니다.