<@U0A71G31CDV> Starrocks에서 두 테이블을 날짜로 나눠서 union al...
# questions-and-troubleshooting
s
@Rocky Starrocks에서 두 테이블을 날짜로 나눠서 union all하고싶은데, 각각 테이블 하나씩 쿼리하면 빠른데 union all 하면 엄청느려서 몇 분씩 걸리는데 해결좀해줘
r
StarRocks에서 각각의 테이블을 조회할 때는 빠르지만 `UNION ALL`로 합쳤을 때 성능이 급격히 저하되는 문제는 주로 *자원 경합(Resource Competition)*이나 쿼리 최적화(Predicate Pushdown) 단계에서 발생합니다. 해결을 위해 다음의 몇 가지 설정을 점검하고 최적화를 시도해 보시기 바랍니다. 1. Phased Scheduler 활성화 (v3.3 이상 권장) StarRocks는 기본적으로 `UNION ALL`의 모든 브랜치를 병렬로 실행합니다. 합쳐야 할 대상이 많을 경우 모든 스캔이 동시에 시작되어 CPU나 메모리 자원을 과도하게 점유하며 느려질 수 있습니다. 이때 `phased_scheduler`를 사용하면 순차적으로 실행하여 자원 사용량을 조절할 수 있습니다.
Copy code
sql
-- 많은 수의 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`로 인해 전체 쿼리의 병렬도가 너무 높아져 오버헤드가 발생하는 경우, 병렬도를 강제로 낮추면 오히려 성능이 개선되는 경우가 있습니다.
Copy code
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.md
s
@Rocky 그러면 union all이 너무 느리니까, full outer join으로 하나도 안겹치게 해서, 하는건 어떄
r
결론부터 말씀드리면, `FULL OUTER JOIN`은 `UNION ALL`보다 훨씬 느리고 자원을 많이 사용하므로 권장하지 않습니다. 데이터가 겹치지 않더라도 `FULL OUTER JOIN`이 더 느린 이유는 다음과 같습니다. 1. 처리 방식의 차이 (Mechaism) *
UNION 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나 메모리 병목이 생길 수 있습니다. 이를 순차적으로 실행하게 바꾸면 성능이 안정화됩니다.
Copy code
sql
-- v3.3 이상인 경우 권장
SET enable_phased_scheduler = true;
SET phased_scheduler_max_concurrency = 1; -- 한 번에 하나씩 처리
② 병렬도(DOP) 낮추기 병렬도가 너무 높으면 오버헤드가 커질 수 있습니다.
Copy code
sql
SET pipeline_dop = 2; -- 또는 1로 설정하여 테스트
③ 조건절 푸시다운 확인 혹시 아래와 같이 쿼리하고 계신가요?
Copy code
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