Sangwon
07/30/2026, 2:22 AMRocky
07/30/2026, 2:23 AMsql
-- 많은 수의 UNION ALL 쿼리 시 메모리 사용량을 줄이고 안정성을 높입니다.
SET enable_phased_scheduler = true;
-- 한 번에 병렬로 실행할 스캔의 개수를 조절합니다 (기본값 2).
SET phased_scheduler_max_concurrency = 2;
2. Predicate Pushdown (조건절 푸시다운) 확인
만약 `UNION ALL`을 서브쿼리로 감싸고 바깥에서 `WHERE date = '...'`와 같은 조건을 걸었다면, 이 조건이 개별 테이블 스캔 단계까지 내려가지 못하고 전체 데이터를 다 읽은 뒤 필터링하고 있을 가능성이 있습니다.
* 해결 방법: 조건을 UNION ALL 안의 각 `SELECT`문에 직접 넣으십시오.
* 확인 방법: EXPLAIN 명령어를 통해 `OlapScanNode`에 `partition predicates`가 제대로 적용되어 있는지 확인하세요.
3. pipeline_dop 조절
`UNION ALL`로 인해 전체 쿼리의 병렬도가 너무 높아져 오버헤드가 발생하는 경우, 병렬도를 강제로 낮추면 오히려 성능이 개선되는 경우가 있습니다.
sql
-- 현재 세션의 병렬 실행 단위(DOP)를 낮춰 자원 경합을 줄입니다.
SET pipeline_dop = 1;
4. UNION vs UNION ALL 구분
`UNION`은 중복 제거를 위해 메모리 소모가 큰 Hash Aggregate 작업을 수행합니다. 중복 제거가 필요 없다면 반드시 `UNION ALL`을 사용하고 있는지 다시 한번 확인해 주세요.
5. 스키마 및 컬럼 확인
`SELECT *`를 사용 중이라면 두 테이블의 컬럼 순서나 타입이 완전히 일치하는지 확인하십시오. 타입이 다르면 StarRocks가 이를 맞추기 위해 내부적으로 형변환(Cast) 연산을 수행하며 성능이 느려질 수 있습니다. 필요한 컬럼만 명시적으로 선택하는 것이 좋습니다.
요약: 시도해 볼 액션 아이템
1. `EXPLAIN ANALYZE <쿼리>`를 실행하여 어느 단계(Scan 혹은 Exchange)에서 시간이 가장 많이 걸리는지 확인합니다.
2. SET enable_phased_scheduler = true; 설정 후 다시 쿼리를 실행해 봅니다.
3. 조건절(WHERE)이 UNION ALL 내부의 각 쿼리에 각각 포함되어 있는지 확인합니다.
만약 위 방법으로도 해결되지 않는다면, 사용 중인 *StarRocks 버전*과 *EXPLAIN 결과*를 공유해 주시면 더 구체적인 진단이 가능합니다.
References
• faq/Sql_faq.md
• sql-reference/System_variable.md
• knowledge/usage/best-practice.md
• sql-reference/sql-statements/table_bucket_part_index/SELECT.mdSangwon
07/30/2026, 2:26 AMRocky
07/30/2026, 2:27 AMUNION ALL: 단순히 두 테이블의 데이터를 위아래로 붙여서 흘려보내는 방식입니다. 별도의 비교 연산이나 해시 테이블 생성이 필요 없습니다.
* FULL OUTER JOIN: 두 테이블의 조인 키를 비교하여 매칭되는 행이 있는지 찾아야 합니다. 이를 위해 *해시 테이블(Hash Table)*을 메모리에 빌드하고, 데이터를 *재분배(Shuffle)*하는 과정이 필수적으로 발생합니다. 데이터가 겹치지 않더라도 엔진은 "겹치지 않는다는 사실"을 확인하기 위해 모든 데이터를 전수 조사해야 하므로 훨씬 무겁습니다.
2. 결과 구조의 차이
* `FULL OUTER JOIN`을 쓰면 결과가 "옆으로" 붙게 됩니다. `UNION ALL`과 같은 결과를 내려면 모든 컬럼에 대해 COALESCE(t1.col, t2.col) 처리를 해주어야 하는데, 이 연산 자체도 추가적인 CPU 비용을 발생시킵니다.
──────────
`UNION ALL`이 느린 진짜 이유와 해결책
각각 쿼리하면 빠른데 합치면 느려지는 현상은 보통 자원 경합(Resource Contention) 때문입니다. 다음 설정을 적용해 보세요.
① 순차 실행 유도 (가장 효과적)
StarRocks는 `UNION ALL`의 모든 브랜치를 동시에 실행하려고 합니다. 이로 인해 스캔이 동시에 몰리면서 I/O나 메모리 병목이 생길 수 있습니다. 이를 순차적으로 실행하게 바꾸면 성능이 안정화됩니다.
sql
-- v3.3 이상인 경우 권장
SET enable_phased_scheduler = true;
SET phased_scheduler_max_concurrency = 1; -- 한 번에 하나씩 처리
② 병렬도(DOP) 낮추기
병렬도가 너무 높으면 오버헤드가 커질 수 있습니다.
sql
SET pipeline_dop = 2; -- 또는 1로 설정하여 테스트
③ 조건절 푸시다운 확인
혹시 아래와 같이 쿼리하고 계신가요?
sql
-- 좋지 않은 예: 합친 후에 밖에서 필터링
SELECT * FROM (
SELECT * FROM table_A
UNION ALL
SELECT * FROM table_B
) WHERE dt = '2023-10-01';
이 경우 조건이 안쪽으로 내려가지 않아 전체 데이터를 다 읽을 수도 있습니다. 반드시 *각 테이블 쿼리 안에 WHERE 절을 직접 작성*하세요.
④ 데이터 타입 일치 확인
두 테이블의 컬럼 순서와 *데이터 타입*이 완전히 일치하는지 확인하세요. 타입이 다르면 내부적으로 CAST 연산이 들어가며 속도가 급격히 느려집니다.
요약
`FULL OUTER JOIN`은 해결책이 아니며, 상황을 더 악화시킬 가능성이 큽니다. `EXPLAIN ANALYZE <쿼리>`를 통해 어느 부분에서 시간이 걸리는지 확인해 보시고, 우선 enable_phased_scheduler = true 설정을 먼저 시도해 보시는 것을 추천드립니다.
References
• faq/Sql_faq.md
• sql-reference/sql-statements/table_bucket_part_index/SELECT.md
• knowledge/usage/best-practice.md
• sql-reference/System_variable.md
References
• faq/Sql_faq.md
• knowledge/usage/best-practice.md
• using_starrocks/async_mv/use_cases/query_rewrite_with_materialized_views.md
• sql-reference/sql-statements/table_bucket_part_index/SELECT.md