RonJay
09/02/2026, 3:20 AMRocky
09/02/2026, 3:20 AMAnalyzeMgr to refresh the statistics cache for connector (external) tables based on logged operations (e.g., OP_ADD_EXTERNAL_BASIC_STATS_META).
* Lazy Loading / Query Trigger: Since v3.4.0, StarRocks also supports query-triggered ANALYZE tasks. If the optimizer finds the cache empty during query planning, it can automatically trigger a background ANALYZE task to populate the stats.
2. Why it might not be working after restart
If your statistics are present in the _statistics_.external_column_statistics table but are not appearing in EXPLAIN plans or the cache, it could be due to:
* Journal Replay Blocking: There is a known issue (e.g., in some v3.x/v4.x versions) where the FE journal replayer can block while attempting to resolve external catalog metadata (like HMS or HDFS) during the statistics cache refresh. If the external catalog is slow or unreachable during startup, the cache loading may fail or time out.
* Cache Capacity: The FE configuration statistic_cache_columns (default: 100,000) limits the number of column statistics held in memory. If you have a very large number of columns across many tables, some may be evicted.
* Catalog Unavailability: If the catalog (e.g., Hive/Iceberg) associated with the stats isn't fully initialized or accessible when the FE starts, the statistics mapping for those tables might fail to load.
3. Recommended Actions & Workarounds
There is no specific "manual load cache from table" command, but you can use these methods to restore the statistics:
* Manually Trigger Analyze: Run a manual ANALYZE for the specific table to force the FE to update both the persistent table and the in-memory cache:
sql
ANALYZE TABLE <table_name> [WITH SYNC MODE];
* Check Replay Logs: Check your fe.log and fe.warn.log for any errors related to AnalyzeMgr, Statistics, or journal replay failures during the startup window. Look for messages like "fail to load external statistics".
* Verify Persistence: Ensure the stats actually exist in the table:
sql
SELECT * FROM _statistics_.external_column_statistics WHERE table_name = 'your_table';
* Check Analyze Status: Run SHOW ANALYZE STATUS or SHOW ANALYZE JOB to see if any background collection tasks failed after the restart.
If the statistics are missing after every restart despite successful ANALYZE runs, it may be a metadata persistence issue or a bug in the version you are using. In such cases, checking for recent GitHub issues or updating to the latest patch release is recommended.
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.mdRonJay
09/02/2026, 9:19 AMRocky
09/02/2026, 9:19 AMANALYZE TABLE 명령을 다시 실행하면 기본적으로 *해당 테이블의 통계치를 처음부터 다시 계산*합니다. 하지만 데이터의 양이 많을 경우 전체를 매번 다시 계산하는 것은 비효율적입니다.
분석 시간을 대폭 단축할 수 있는 몇 가지 방법은 다음과 같습니다.
1. 증분 분석 (특정 파티션만 분석)
전체 테이블이 아닌, 데이터가 새로 추가되거나 변경된 *특정 파티션만 지정*하여 분석할 수 있습니다. 이는 가장 효과적인 시간 단축 방법입니다.
sql
ANALYZE TABLE <table_name> PARTITION (p20231001, p20231002);
2. 샘플링 분석 (SAMPLE) 사용
데이터 전체를 읽는 FULL 방식 대신 일부만 샘플링하여 통계를 산출하는 SAMPLE 방식을 사용하세요. 대용량 테이블에서 정확도 손실을 최소화하면서 속도를 획기적으로 높일 수 있습니다.
sql
-- 테이블의 일부 데이터만 샘플링하여 분석
ANALYZE SAMPLE TABLE <table_name>;
* 팁: `PROPERTIES`를 통해 샘플링할 최소 행 수를 조정할 수 있습니다.
ANALYZE SAMPLE TABLE <table_name> PROPERTIES("statistic_sample_collect_rows" = "1000000");
3. 병렬 처리 수준(Parallelism) 높이기
통계 수집 시 사용하는 병렬도를 높여 실행 시간을 단축할 수 있습니다. 세션 변수를 설정한 후 `ANALYZE`를 실행하세요.
sql
-- 병렬도 설정 (기본값 1, 더 높은 값으로 설정 가능)
SET statistic_collect_parallel = 4;
ANALYZE TABLE <table_name>;
4. 필요한 컬럼만 선택적으로 분석
테이블의 모든 컬럼이 아닌, 쿼리 조건(WHERE, JOIN, GROUP BY)에 자주 사용되는 컬럼만 지정하여 분석 시간을 줄일 수 있습니다.
sql
-- 특정 컬럼만 분석
ANALYZE TABLE <table_name>(col1, col2);
-- (v3.5 이상) 쿼리에 사용된 적이 있는 조건 컬럼만 자동으로 선택하여 분석
ANALYZE TABLE <table_name> PREDICATE COLUMNS;
5. 자동 수집 정책 활용 (Health 기반)
StarRocks는 데이터 변경률이 일정 수준(기본 20% 이상)을 넘을 때만 통계를 갱신하도록 하는 Auto Collect 기능을 제공합니다. 이 기능을 켜두면 불필요한 재분석을 시스템이 알아서 방지합니다.
* `statistic_auto_collect_ratio`: 데이터 변경 임계치 (기본 0.8, 즉 20% 변경 시 수행)
요약:
이미 계산된 값이 있더라도 수동으로 `ANALYZE`를 호출하면 다시 계산을 수행하므로, 시간이 너무 오래 걸린다면 *`SAMPLE` 키워드*를 추가하거나 *`PARTITION`을 지정*하여 실행하는 것을 권장합니다.
참고 문서
• Gather statistics for CBO
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• administration/management/BE_configuration.mdRonJay
09/02/2026, 9:37 AMRocky
09/02/2026, 9:38 AMANALYZE) 속도를 높이려면, 설정값의 종류(세션 변수 vs FE 설정)를 정확히 구분하여 적용해야 합니다.
사용자께서 statistic_collect_parallel 설정을 찾지 못하신 이유는 해당 값이 *FE 설정(FE Configuration)이 아닌 세션 변수(Session Variable)*이기 때문일 가능성이 큽니다.
1. statistic_collect_parallel 확인 및 설정법
이 설정은 `ADMIN SHOW CONFIG`로 나오지 않으며, 일반 SQL 문으로 확인 및 설정해야 합니다.
* 확인: SHOW VARIABLES LIKE 'statistic_collect_parallel';
* 설정: SET statistic_collect_parallel = 4; (현재 세션) 또는 SET GLOBAL statistic_collect_parallel = 4; (전체 적용)
_ _역할:* BE에서 통계 수집 쿼리를 수행할 때의 병렬도를 조절합니다.
──────────
2. v4.1.1에서 ANALYZE를 더 빠르게 수행하는 방법
만약 세션 변수 조정만으로 부족하다면, 다음의 최신 기능들을 조합하여 속도를 개선할 수 있습니다.
① ANALYZE SAMPLE TABLE 사용 (가장 추천)
StarRocks v3.5부터 도입된 Table Sample 방식은 기존의 Row 단위 샘플링보다 훨씬 빠릅니다. 물리적 데이터 블록 단위로 샘플링하기 때문에 대용량 테이블에서 압도적인 속도 차이를 보입니다.
sql
ANALYZE SAMPLE TABLE <table_name>;
② statistic_collect_max_row_count_per_query 조정 (FE 설정)
하나의 대규모 ANALYZE 작업을 여러 개의 작은 쿼리로 쪼개서 실행하도록 설정합니다. 이 값이 작을수록 작업이 더 많이 분할되어 BE들 사이에서 병렬로 처리될 기회가 많아집니다.
* 설정: ADMIN SET FRONTEND CONFIG ("statistic_collect_max_row_count_per_query" = "1000000000"); (기본값 50억)
③ 특정 컬럼/파티션만 지정
불필요한 컬럼이나 과거 데이터까지 모두 분석할 필요가 없다면 범위를 제한하세요.
* 특정 컬럼만: ANALYZE TABLE <table_name>(col1, col2);
* 특정 파티션만: ANALYZE TABLE <table_name> PARTITION (p202401, p202402);
④ 외부 테이블(External Table)인 경우 추가 설정
Hive, Iceberg 등의 외부 테이블 통계 수집 속도를 높이려면 FE 설정을 통해 동시 실행 작업 수를 늘릴 수 있습니다.
* 설정: ADMIN SET FRONTEND CONFIG ("connector_table_query_trigger_analyze_max_running_task_num" = "4"); (기본값 2)
요약
1. *세션 변수*인 `SET statistic_collect_parallel = 4;`를 먼저 실행해 보세요.
2. 분석 실행 시 SAMPLE 키워드를 반드시 추가하세요.
3. 그래도 느리다면 statistic_collect_max_row_count_per_query 값을 낮추어 병렬 분할 실행을 유도하세요.
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• release_notes/release-3.5.md
References
• administration/management/FE_configuration.md
• using_starrocks/Cost_based_optimizer.md
• administration/management/resource_management/Query_management.md
• faq/Sql_faq.mdRonJay
09/03/2026, 5:51 AMRocky
09/03/2026, 5:51 AMEXPLAIN COSTS 출력 결과에서 SCAN 연산자는 데이터를 저장소(Local Disk 또는 Remote S3/HDFS 등)에서 읽어오는 가장 기초적인 단계를 의미합니다.
1. SCAN Operator의 주요 비용 지표 설명
EXPLAIN COSTS 실행 시 Estimates: {row: ..., cpu: ..., memory: ..., network: ..., cost: ...} 형태로 출력되는 값들은 *CBO(Cost-Based Optimizer)*가 최적의 경로를 찾기 위해 계산한 예측치입니다.
* row (Cardinality): 해당 스캔을 통해 결과적으로 반환될 것으로 예상되는 행(row)의 수입니다. 통계 정보와 WHERE 절의 필터(Predicate) 조건에 따라 결정됩니다.
* cpu: 데이터를 읽고, 디코딩(uncompress)하고, 조건문을 체크(Filter)하는 데 소비되는 계산 리소스를 수치화한 것입니다.
* memory: 스캔 중 버퍼링이나 메타데이터 로딩에 필요한 메모리 양입니다.
* network: 스캔 단계에서는 보통 0인 경우가 많지만, 외부 테이블 스캔이나 데이터 셔플링이 포함될 경우 네트워크 비용이 계산됩니다.
* cost: 위 모든 요소(CPU, IO, Network 등)에 가중치를 곱해 합산한 *최종 점수*입니다. CBO는 이 cost 합계가 가장 낮은 실행 계획을 선택합니다.
* partitionRatio / tabletRatio: 전체 파티션/태블릿 중 실제로 몇 개를 읽는지 보여줍니다. (예: `1/10`은 10개 중 1개만 읽음 -> Partition Pruning 적용 확인 가능)
──────────
2. Iceberg 테이블에서의 SCAN 동작 방식
Iceberg와 같은 데이터 레이크 테이블의 경우, StarRocks는 Connector Scan 방식으로 동작하며 다음과 같은 특성을 가집니다.
① 메타데이터 기반 최적화 (FE 단계)
StarRocks FE는 Iceberg의 메타데이터(Snapshot, Manifest List, Manifest File)를 읽어 실제 읽어야 할 데이터 파일 리스트를 추립니다.
* Partition Pruning: 쿼리 조건에 맞는 파티션만 필터링합니다.
* File Pruning: 파일 단위의 Min/Max 통계를 확인하여 조건에 부합하지 않는 데이터 파일은 스캔 대상에서 제외합니다.
* Metadata Caching: StarRocks는 Iceberg 메타데이터를 FE 메모리와 디스크에 캐싱하여, 매번 S3/HDFS를 조회하는 비용을 줄입니다. (v3.3+ 에서는 자동 갱신 지원)
② 적응형 쿼리 플래닝 (Adaptive Planning)
Iceberg는 메타데이터 자체가 매우 클 수 있습니다. StarRocks는 메타데이터 양에 따라 전략을 바꿉니다.
* Local Plan: 메타데이터가 적으면 FE가 직접 분석하여 실행 계획을 수립합니다.
* Distributed Plan: 읽어야 할 Manifest 파일이 너무 많으면, FE가 직접 분석하지 않고 *BE/CN 노드들에게 메타데이터 분석 작업을 분산*시켜 플래닝 속도를 높입니다.
③ 데이터 스캔 및 푸시다운 (BE 단계)
실제 데이터 파일(Parquet/ORC)을 읽을 때 BE는 다음 최적화를 수행합니다.
* Columnar Scan: 필요한 컬럼만 선택적으로 읽습니다.
* Predicate Pushdown: WHERE 조건을 데이터 파일을 읽는 시점에 적용하여 불필요한 IO를 줄입니다. (Parquet의 Row Group/Page 단위 필터링 포함)
* IO Acceleration: Data Cache(디스크 캐시)를 활성화한 경우, 한 번 읽은 Iceberg 데이터 블록은 BE 로컬 디스크에 저장되어 다음 쿼리 시 원격 저장소 접속 없이 즉시 읽습니다.
요약
* SCAN 비용이 너무 높다면 *Partition Pruning*이 제대로 안 되고 있거나, *통계 정보(ANALYZE)*가 부정확하여 row 예측이 잘못되었을 가능성이 큽니다.
* Iceberg 스캔 시에는 *메타데이터 캐시*와 Data Cache 설정이 성능(및 Cost)에 가장 큰 영향을 미칩니다.
References
• best_practices/query_tuning/query_planning.md
• data_source/catalog/iceberg/iceberg_catalog.md
• best_practices/query_tuning/query_profile_operator_metrics.md
References
• data_source/feature-support-data-lake-analytics.md
• data_source/catalog/iceberg/iceberg_catalog.mdRonJay
09/03/2026, 7:32 AMRocky
09/03/2026, 7:32 AMsql
-- 프로파일 수집 활성화 (세션 수준)
SET enable_profile = true;
-- 쿼리 실행
SELECT ... FROM ... ;
-- 실행한 쿼리의 ID 확인
SELECT last_query_id();
-- 프로파일 출력 (위에서 확인한 ID 입력)
SELECT get_query_profile('019b364f-10c4-704c-b79a-af2cc3a77b89')\G
2. 네트워크 관련 주요 지표 (Metrics)
출력된 Profile 내용 중 *`EXCHANGE_SINK_OPERATOR`*와 EXCHANGE_SOURCE_OPERATOR 섹션을 찾으세요. 노드 간 데이터 이동이 일어나는 지점입니다.
① 전송 측 (Exchange Sink) - 데이터를 보내는 노드
* NetworkTime: 데이터 패킷이 네트워크를 통해 전송되는 데 순수하게 소요된 시간입니다. (수신 확인 제외)
* WaitTime: 수신 측의 큐가 가득 차서 전송이 대기(Backpressure)된 시간입니다. 이 값이 크면 수신 노드의 처리 속도가 느리거나 네트워크 병목이 있음을 의미합니다.
* RpcAvgTime / RpcCount: RPC 호출 한 번당 평균 시간과 총 횟수입니다. 네트워크 지연이 높으면 `RpcAvgTime`이 증가합니다.
* NetworkBandwidth: 측정된 네트워크 대역폭입니다.
② 수신 측 (Exchange Source) - 데이터를 받는 노드
* ClosureBlockTime: 데이터를 기다리느라 수신자가 차단(Blocked)된 시간입니다. 네트워크가 느려 데이터가 늦게 도착할 때 이 값이 커집니다.
* DeserializeChunkTime / DecompressChunkTime: 받은 데이터를 풀고 해석하는 시간입니다. CPU 부하가 높으면 이 시간이 길어집니다.
③ 요약 지표 (Summary)
Profile 상단부의 Execution Overview 섹션에서도 전체적인 합계를 볼 수 있습니다.
* QueryCumulativeNetworkTime: 쿼리 전체에서 모든 Exchange 노드가 네트워크 전송에 사용한 누적 시간입니다.
3. 분석 팁
* `WaitTime`이 길 경우: 수신 노드(Receiver)의 연산(Join/Aggregation) 부하가 너무 커서 데이터를 제때 못 받아주는 상황일 수 있습니다.
* `NetworkTime`이나 `RpcAvgTime`이 길 경우: 실제 물리적인 네트워크 대역폭 부족이나 스위치/NIC 설정 문제, 혹은 노드 간 물리적 거리가 멀어 발생하는 지연일 수 있습니다.
* 데이터 크기 확인: `BytesSent`가 예상보다 너무 크다면, 쿼리 계획에서 `Broadcast Join`이 잘못 선택되어 불필요하게 많은 데이터를 네트워크로 흘리고 있는지 확인해야 합니다.
References
• best_practices/query_tuning/query_profile_operator_metrics.md
• best_practices/query_tuning/query_profile_overview.md
• best_practices/query_tuning/query_planning.md
• administration/management/resource_management/Query_management.md
References
• best_practices/query_tuning/query_profile_operator_metrics.md
• best_practices/query_tuning/query_profile_overview.mdRonJay
09/06/2026, 7:51 AMRocky
09/06/2026, 7:51 AMEXPLAIN COSTS 실행 시 출력되는 *`(MBE)`*는 Metadata-Based Estimation (또는 내부적으로 Mock-Based Estimation)을 의미합니다. 이는 옵티마이저가 실제 데이터 통계 정보(ANALYZE)를 찾지 못해, 테이블의 기본 메타데이터나 사전에 정의된 *기본값(Heuristics)*을 바탕으로 추정한 상태임을 나타냅니다.
통계가 전혀 없는 상황에서 데이터 규모가 과소추정(Underestimation)되는 구체적인 이유는 다음과 같습니다.
1. 기본 행 수(Default Row Count) 사용
StarRocks 옵티마이저는 통계 정보가 없을 때 테이블의 크기를 알 수 없습니다. 이 경우 `MockBasedEstimator`가 동작하며, 테이블의 행 수를 매우 작은 고정된 상수(예: 10,000행 또는 그 이하)로 가정하는 경우가 많습니다. 실제 데이터가 수억 건이라 하더라도 옵티마이저는 1만 건 정도로 인식하게 됩니다.
2. 고정된 선택도(Fixed Selectivity) 적용
WHERE 절에 필터 조건이 있을 때, 실제 데이터 분포(NDV, Histogram 등)를 모르면 옵티마이저는 임의의 비율을 적용합니다.
* 예를 들어, col = 'value' 조건에 대해 전체의 10%나 1%만 남을 것이라고 단순 가정합니다.
* 기본 행 수 자체가 작게 설정된 상태에서 이러한 고정 선택도까지 적용되면, 최종 결과 행 수는 매우 적게 추정됩니다.
3. 메타데이터의 한계
Iceberg나 Hive 같은 외부 테이블의 경우, 파일 크기나 파일 개수 같은 메타데이터는 알 수 있지만, 필터 조건에 의해 얼마나 많은 행이 걸러질지는 통계 정보 없이는 알 수 없습니다. 옵티마이저는 보수적으로(또는 기본 규칙에 따라) 계산하려다 보니 실제보다 훨씬 적은 비용으로 계산하게 됩니다.
──────────
과소추정의 위험성
통계가 과소추정되면 옵티마이저는 다음과 같은 잘못된 판단을 내릴 가능성이 큽니다.
* 잘못된 Join 순서: 아주 큰 테이블을 작은 테이블로 오판하여 Join의 Inner/Outer 위치를 바꾸거나, 대량의 데이터를 네트워크로 뿌리는 *Broadcast Join*을 선택하여 *OOM(Out of Memory)*을 유발할 수 있습니다.
* 불필요한 Plan 생성: 데이터가 적다고 판단하여 병렬 처리를 낮게 설정하거나 비효율적인 실행 경로를 선택합니다.
해결 방법
가장 확실한 해결책은 해당 테이블에 대해 *통계를 수집*하는 것입니다.
sql
-- 특정 테이블의 통계 수집
ANALYZE TABLE <table_name>;
-- 수집 후 다시 확인
EXPLAIN COSTS <query>;
통계가 정상적으로 수집되면 (MBE) 표시가 사라지거나 (FULL) 또는 (SAMPLE) 등으로 변경되며, row 예측치가 실제와 가깝게 수정됩니다.
References
• using_starrocks/Cost_based_optimizer.md
• best_practices/query_tuning/query_planning.md
• sql-reference/sql-statements/cluster-management/plan_profile/EXPLAIN.md
References
• using_starrocks/Cost_based_optimizer.md
• best_practices/query_tuning/query_planning.md
• sql-reference/sql-statements/cluster-management/plan_profile/EXPLAIN.md
• sql-reference/sql-statements/cluster-management/plan_profile/EXPLAIN_ANALYZE.md
• best_practices/query_tuning/query_profile_operator_metrics.md
• best_practices/query_tuning/query_profile_overview.md
• data_source/feature-support-data-lake-analytics.md
• administration/management/resource_management/Query_queues.md
References
• using_starrocks/Cost_based_optimizer.md
• using_starrocks/accelerate-cardinality-preserving-joins.mdRonJay
09/06/2026, 8:58 AMRocky
09/06/2026, 8:58 AMinformation_schema.tables 쿼리를 통해 해당 객체의 타입을 확인할 수 있습니다.
sql
SELECT
TABLE_SCHEMA,
TABLE_NAME,
TABLE_TYPE
FROM information_schema.tables
WHERE TABLE_NAME = '조회할_이름';
* BASE TABLE: 물리적으로 데이터가 저장된 일반 테이블입니다.
* VIEW: 쿼리 정의만 저장된 가상 뷰입니다.
* SYSTEM VIEW: 시스템 정보를 담은 뷰입니다.
2. SHOW CREATE 명령어를 통한 확인
객체의 생성 구문을 직접 확인하여 뷰인지 테이블인지 알 수 있습니다.
* 뷰인지 확인:
sql
SHOW CREATE VIEW 테이블_혹은_뷰_이름;
이 명령어는 대상이 일반 뷰 또는 *Materialized View(구체화 뷰)*일 때만 정의를 보여줍니다. 일반 테이블인 경우 에러가 발생합니다.
* 테이블인지 확인:
sql
SHOW CREATE TABLE 테이블_혹은_뷰_이름;
일반 테이블이라면 CREATE TABLE ... 구문이 출력됩니다.
3. Materialized View(MV)가 특정 뷰를 참조하는지 확인
만약 "구체화 뷰(MV)가 다른 뷰를 기반으로 생성되었는가"를 확인하고 싶다면 아래 쿼리를 사용합니다.
sql
-- 비동기 MV의 정의를 확인하여 기반이 되는 뷰/테이블 파악
SHOW CREATE MATERIALIZED VIEW MV_이름;
출력되는 CREATE MATERIALIZED VIEW ... AS SELECT ... 구문 내부의 FROM 절을 보면 어떤 뷰나 테이블을 기반으로 데이터가 생성되는지 확인할 수 있습니다.
요약
* 객체 종류 확인: SELECT TABLE_TYPE FROM information_schema.tables WHERE TABLE_NAME = '...'
* 상세 정의 확인: SHOW CREATE VIEW ... (뷰일 경우) 또는 SHOW CREATE TABLE ... (테이블일 경우)
References
• sql-reference/information_schema/tables.md
• sql-reference/sql-statements/View/SHOW_CREATE_VIEW.md
• using_starrocks/async_mv/Materialized_view.md
References
• sql-reference/sql-statements/View/SHOW_CREATE_VIEW.md
• using_starrocks/async_mv/Materialized_view.md
• data_source/feature-support-data-lake-analytics.md
• sql-reference/sql-statements/table_bucket_part_index/SHOW_CREATE_TABLE.md
• data_source/catalog/deltalake_catalog.mdRonJay
09/07/2026, 7:44 AMRocky
09/07/2026, 7:44 AMenable_get_stats_from_external_metadata 설정값과 *`ANALYZE`*를 통해 수집된 내부 통계 정보 사이에는 명확한 우선순위와 상호작용이 존재하며, 설정에 따라 쿼리 최적화 결과가 달라질 수 있습니다.
핵심 요점은 *"StarRocks 내부 통계가 외부 메타데이터보다 우선순위가 높다"*는 점입니다.
1. 통계 정보 참조 우선순위
StarRocks 옵티마이저(CBO)가 통계 정보를 찾는 순서는 다음과 같습니다.
1. StarRocks 내부 수집 통계 (ANALYZE 실행 결과): 가장 높은 우선순위를 가집니다. 특정 컬럼에 대해 `ANALYZE`를 수행했다면, 외부 메타데이터 설정과 무관하게 이 정보를 사용합니다.
2. 외부 메타데이터 통계 (HMS, Iceberg 등): `ANALYZE`를 수행하지 않은 컬럼에 대해, `enable_get_stats_from_external_metadata`가 `true`일 경우 외부 소스(Hive Metastore, Iceberg Manifest 등)에서 정보를 가져오려고 시도합니다.
3. 기본 추정치 (MBE): 위 두 정보가 모두 없거나 설정이 `false`인 경우, 파일 크기나 개수 등 아주 기본적인 정보로 행 수를 추측(Metadata-Based Estimation)하며, 이 과정에서 과소추정(대개 1만 행 등)이 발생할 가능성이 큽니다.
2. 일부 컬럼만 ANALYZE 했을 때의 동작
질문하신 것처럼 일부 컬럼만 수집된 경우, 설정에 따라 다음과 같이 동작이 달라집니다.
* enable_get_stats_from_external_metadata = true 일 때:
* `ANALYZE`된 컬럼: StarRocks 내부의 정밀한 통계를 사용합니다.
* `ANALYZE`되지 않은 컬럼: 외부 메타데이터에서 NDV(Unique 값 개수), Null Count, Min/Max 정보를 가져와 보충합니다.
* 결과: 전체적으로 쿼리 계획이 비교적 정확해집니다.
* enable_get_stats_from_external_metadata = false 일 때 (기본값):
* `ANALYZE`된 컬럼: 내부 통계를 사용합니다.
* `ANALYZE`되지 않은 컬럼: 외부 메타데이터를 보지 않으므로, 해당 컬럼에 필터나 조인이 걸릴 경우 옵티마이저는 정확한 분포를 몰라 기본 추정치(MBE)를 사용합니다.
* 결과: 분석되지 않은 컬럼이 포함된 필터 조건에서 데이터 규모를 잘못 판단하여 성능이 저하될 수 있습니다.
3. 테이블 행 수(Row Count)의 차이
`ANALYZE TABLE tbl(col1)`과 같이 특정 컬럼만 지정해서 실행하더라도, StarRocks는 해당 테이블의 *전체 행 수(Row Count)*를 함께 기록합니다.
따라서 `enable_get_stats_from_external_metadata`가 `false`여도, 일부 컬럼이라도 `ANALYZE`를 돌렸다면 테이블 전체 규모(Row Count)는 어느 정도 인지된 상태가 됩니다. 하지만 *개별 컬럼의 분포(NDV 등)*는 여전히 알 수 없으므로 해당 컬럼이 쿼리 조건에 쓰일 때 결과가 달라지게 됩니다.
요약 및 권장사항
* 결과가 달라지는가? 네, `ANALYZE`되지 않은 컬럼이 쿼리에 포함될 때 이 설정이 `true`이면 외부 정보를 활용해 더 나은 계획을 세우고, `false`이면 부정확한 추정치를 사용합니다.
* 권장사항: 외부 데이터 레이크(Iceberg 등)를 조회할 때 모든 컬럼을 일일이 ANALYZE 하기 어렵다면, 이 설정을 *`true`*로 켜서 기본 통계를 확보하고, 성능이 중요한 핵심 컬럼만 `ANALYZE`로 정밀 관리하는 것이 효율적입니다.
References
• using_starrocks/Cost_based_optimizer.md
• sql-reference/System_variable.md
• data_source/catalog/iceberg/iceberg_catalog.md
• best_practices/query_tuning/query_planning.md
References
• using_starrocks/Cost_based_optimizer.md
• data_source/catalog/catalog_overview.md
• table_design/table_design.mdRonJay
09/09/2026, 2:26 AMRocky
09/09/2026, 2:26 AMcn.warn 로그에 발생하는 txn_log of txn: [ID] not found and can not find the tablet_meta 에러는 주로 *StarRocks 공유 스토리지(Shared-data) 모드*에서 데이터 적재(Load) 후 Publish Version(버전 발행) 단계에서 발생합니다.
이 에러의 핵심 원인은 *FE(Front-end)가 특정 트랜잭션을 완료(Commit)하려고 시도하는데, 정작 해당 작업을 수행해야 할 CN(Compute Node)이나 BE에서 관련 트랜잭션 기록(txn_log)이나 태블릿 정보(tablet_meta)를 찾을 수 없기 때문*입니다.
상세한 원인과 상황은 다음과 같습니다.
1. 트랜잭션 취소 또는 만료 (가장 흔한 원인)
적재 작업이 진행되다가 타임아웃, 사용자 강제 취소(CANCEL LOAD), 혹은 시스템 오류로 인해 트랜잭션이 이미 중단된 경우입니다.
* 트랜잭션이 중단되면 CN은 메모리나 로컬 캐시에 보관하던 임시 `txn_log`를 삭제합니다.
* 하지만 FE의 버전 발행 스레드(Publish Version Daemon)가 이 사실을 즉시 인지하지 못하고 해당 CN에 "버전 발행을 완료하라"는 요청을 보낼 때, CN은 기록이 없으므로 해당 에러를 출력합니다.
2. 가비지 컬렉션(GC)에 의한 정리
StarRocks는 비정상적으로 종료되거나 오래된 트랜잭션 로그를 주기적으로 정리합니다.
* 적재 작업이 비정상적으로 길어져서 transaction_clean_interval 등의 설정에 의해 이미 정리된 상태에서 뒤늦게 FE가 접근하려고 할 때 발생할 수 있습니다.
3. 메타데이터 불일치 (Desync)
FE가 관리하는 트랜잭션 상태와 CN/BE가 로컬에 들고 있는 상태가 일치하지 않을 때 발생합니다.
* CN이 재시작되면서 로컬 캐시(메타데이터 캐시)가 유실되었으나, FE는 여전히 해당 CN이 트랜잭션 정보를 가지고 있다고 판단하여 요청을 보내는 경우입니다.
4. 테이블/파티션 삭제 또는 Truncate
데이터 적재가 완료되기 직전에 해당 테이블이나 파티션을 `DROP`하거나 `TRUNCATE`한 경우, 관련 태블릿 메타데이터가 사라지면서 이 에러가 발생할 수 있습니다.
──────────
확인 및 해결 방법
1. 적재 이력 확인:
에러 로그에 찍힌 `txn_id`를 사용하여 어떤 작업이었는지 확인합니다.
sql
-- 트랜잭션 상태 확인
SELECT * FROM information_schema.be_txns WHERE TXN_ID = [에러로그의_ID];
-- 최근 취소된 로드 작업 확인
SHOW LOAD WHERE STATE = 'CANCELLED';
2. 로그 확인: `fe.log`에서 해당 `txn_id`와 관련된 `Publish version timeout`이나 Transaction cancel 로그가 있는지 확인하십시오.
3. 일시적인 현상인지 확인: 만약 특정 적재 작업 취소 직후에 발생하는 일시적인 WARN 로그라면 시스템 성능이나 데이터 정합성에는 큰 영향을 주지 않으므로 무시해도 무방합니다. 하지만 모든 적재가 실패하며 이 로그가 반복된다면, FE와 CN 간의 네트워크 상태나 CN의 리소스(메모리 부족 등)를 점검해야 합니다.
결론적으로, 이 메시지는 "이미 끝났거나 사라진 작업에 대해 마무리를 요청받았을 때" 나타나는 경고성 로그일 가능성이 높습니다.
References
• sql-reference/information_schema/be_txns.md
• faq/loading/Loading_faq.md
• administration/management/BE_configuration.md
References
• administration/Meta_recovery.md
• faq/loading/Loading_faq.md
• sql-reference/information_schema/be_txns.md
• faq/Sql_faq.md
• administration/management/BE_configuration.mdRonJay
09/09/2026, 4:24 AMRocky
09/09/2026, 4:24 AMstarrocks_fe_txn_publish_ack_latency_ms 지표는 StarRocks의 데이터 적재 트랜잭션 단계 중, *커밋된 데이터가 최종적으로 "가시성(Visible)"을 확보하기까지 걸리는 마지막 응답 지연 시간*을 의미합니다.
StarRocks의 트랜잭션 흐름(특히 v4.0 이상 메트릭 기준)에서 이 지표가 갖는 상세 의미는 다음과 같습니다.
1. 지표의 정의
* 측정 구간: ready-to-finish 시점부터 트랜잭션이 최종적으로 VISIBLE 상태로 마킹되는 finish 시점까지의 시간입니다.
* 의미: 트랜잭션의 Publish 단계(데이터를 쿼리 가능한 상태로 만드는 과정) 중 가장 마지막 단계에 해당하며, 모든 태블릿의 버전 업데이트가 확인된 후 FE(Front-end) 내부에서 최종 승인(Acknowledgment)을 처리하는 데 걸리는 시간입니다.
2. 전체 트랜잭션 내 위치
트랜잭션 가시성 확보 과정은 다음과 같은 세부 지표로 나뉩니다:
* `publish_schedule_latency`: 커밋 후 발행(Publish) 작업이 스케줄링될 때까지 대기 시간
* `publish_execute_latency`: 실제 발행 작업이 실행되는 시간
* `publish_can_finish_latency`: 발행 완료 후 종료 가능 여부를 판단하는 시간
* publish_ack_latency (해당 지표): 모든 준비가 끝나고 최종적으로 사용자에게 데이터를 노출하기 전 마지막 확정 시간
3. 이 지표가 높을 때의 영향 및 원인
이 수치가 높다면 *데이터 적재(Load) 작업은 끝났는데, 정작 SELECT 쿼리에서 데이터가 바로 보이지 않는 현상*이 발생합니다.
* 주요 원인:
* FE 부하: Leader FE가 너무 많은 트랜잭션을 동시에 처리하거나 메타데이터 업데이트 작업이 밀려 있는 경우.
* 태블릿 개수 과다: 테이블의 파티션이나 버킷 수가 너무 많아 업데이트해야 할 메타데이터 양이 방대한 경우.
* 네트워크/디스크 I/O 지연: 공유 스토리지(Shared-data) 모드에서 메타데이터를 스토리지에 기록하는 과정에서의 지연.
4. 참고 사항
* 이 지표는 Leader FE 노드에서만 유의미한 값을 출력합니다 (Follower FE에서는 `is_leader="false"`로 표시됨).
* 단위는 밀리초(ms)이며, summary 타입으로 제공되어 0.99, 0.95 등 백분위(Quantile) 값을 통해 지연 현상을 파악할 수 있습니다.
References
• administration/management/monitoring/metrics.md
• administration/management/FE_configuration.md
• using_starrocks/async_mv/Materialized_view.md
References
• administration/management/monitoring/metrics.md
• administration/management/FE_configuration.mdRonJay
09/09/2026, 7:49 AMRocky
09/09/2026, 7:49 AMANALYZE)을 수동으로 실행하거나, 주기적인 자동 작업으로 등록하는 방법은 다음과 같습니다.
1. 수동 실행 (일회성)
특정 시점에 즉시 통계를 수집하고 싶을 때 사용합니다.
* 전체 컬럼 수집:
sql
ANALYZE TABLE 테이블명;
* 특정 컬럼만 수집 (권장):
sql
ANALYZE TABLE 테이블명 (컬럼1, 컬럼2);
* 샘플링 수집 (대용량 테이블 시 유용):
sql
ANALYZE SAMPLE TABLE 테이블명;
* 실행 방식 선택: `WITH SYNC MODE`(완료될 때까지 대기) 또는 `WITH ASYNC MODE`(백그라운드 실행)를 추가할 수 있습니다.
──────────
2. 주기적 자동 수집 설정 (CREATE ANALYZE)
StarRocks는 기본적으로 데이터 변경량(기본 80% 이상 변경 시)을 감지하여 자동 수집을 수행하지만, 사용자가 직접 조건을 정의하여 주기적인 작업을 생성할 수 있습니다.
구문 예시
sql
CREATE ANALYZE [FULL | SAMPLE] TABLE 테이블명 (컬럼1, 컬럼2)
PROPERTIES (
"statistic_auto_collect_ratio" = "0.2", -- 데이터의 20%가 변경되면 수집 트리거
"statistic_auto_collect_interval" = "3600" -- 수집 주기 (단위: 초, 예: 1시간마다 체크)
);
주요 설정 값 (PROPERTIES)
* statistic_auto_collect_ratio: 통계 정보가 '건강하지 않다'고 판단하는 데이터 변경 비율입니다 (기본값 0.8). 이 값을 낮추면 더 자주 수집됩니다.
* statistic_auto_collect_interval: 자동 수집 작업을 체크하는 주기(초 단위)입니다. 설정하지 않으면 시스템 기본값(작은 테이블 0, 큰 테이블 12시간)을 따릅니다.
* statistic_sample_collect_rows: 샘플링 수집 시 최소 행 수입니다.
──────────
3. 관리 및 확인 명령어
* 진행 중인 작업 확인:
sql
SHOW ANALYZE STATUS [WHERE TABLE_NAME = '테이블명'];
* 등록된 자동 수집 작업(Job) 목록 확인:
sql
SHOW ANALYZE JOB;
* 자동 수집 작업 삭제:
sql
DROP ANALYZE JOB [Job_ID];
* 수집된 통계 메타데이터 확인:
sql
SHOW STATS META [WHERE TABLE_NAME = '테이블명'];
팁
* 외부 카탈로그(Iceberg, Hive 등): 외부 테이블도 동일하게 `CREATE ANALYZE`로 등록 가능하며, 별도 설정이 없다면 약 5분 간격(statistic_collect_interval_sec)으로 데이터 업데이트 여부를 체크합니다.
* 성능 영향: ANALYZE 작업은 클러스터 리소스를 소모하므로, 데이터 변화가 잦은 핵심 컬럼 위주로 수집하거나 사용량이 적은 시간에 수집되도록 비율(ratio)과 주기(interval)를 조정하는 것이 좋습니다.
References
• using_starrocks/Cost_based_optimizer.md
• sql-reference/sql-statements/cbo_stats/CREATE_ANALYZE.md
• sql-reference/sql-statements/cbo_stats/SHOW_ANALYZE_STATUS.md
• sql-reference/sql-statements/cbo_stats/ANALYZE_TABLE.md
References
• using_starrocks/Cost_based_optimizer.md
• sql-reference/sql-statements/cbo_stats/CREATE_ANALYZE.mdRonJay
09/09/2026, 8:04 AMRocky
09/09/2026, 8:04 AMEXPLAIN ANALYZE 명령어를 통해 프로파일을 확인하십시오. IcebergScanNode 또는 HdfsScanNode 섹션에서 다음 지표들을 체크합니다.
* NumFiles vs TotalRawSize:
* 스캔하는 파일 개수(NumFiles)는 수천 개인데, 전체 데이터 용량(TotalRawSize)이 수 MB~수백 MB 수준이라면 명백한 Small Files 이슈입니다.
* WaitRowsTime:
* BE가 데이터를 실제로 처리하기 위해 대기한 시간입니다. 이 수치가 높다면 네트워크 I/O나 파일 Open 대기 시간이 길다는 뜻입니다.
* ScanTime 내 상세 지표:
* FileOpenTime: 파일 하나하나를 여는 데 걸린 총 시간입니다. 파일이 많을수록 이 수치가 비정상적으로 커집니다.
* MetadataFetchTime: Iceberg Manifest 파일을 읽고 데이터 파일 리스트를 필터링하는 데 걸린 시간입니다.
* IOBufferFullWaitTime:
* 데이터는 빨리 못 오는데 CPU는 놀고 있을 때 발생합니다.
증거 제시 방법: "전체 쿼리 시간 10초 중, 실제 연산(Aggregate/Join)은 1초 미만인데, `FileOpenTime`과 `WaitRowsTime`이 8초 이상을 점유함"을 보여주면 됩니다.
──────────
2. Iceberg 메타데이터 쿼리 (물리적 증거)
StarRocks를 통해 Iceberg의 시스템 테이블을 직접 조회하여 파일당 평균 크기를 산출합니다.
sql
-- 테이블 내 파일들의 평균 크기 및 개수 확인
SELECT
count(*) as total_file_count,
avg(file_size_in_bytes) / 1024 / 1024 as avg_file_size_mb,
sum(file_size_in_bytes) / 1024 / 1024 / 1024 as total_gb
FROM <catalog_name>.<db_name>."<table_name>$files";
* 판단 기준: Iceberg에서 권장하는 파일 크기는 보통 128MB ~ 512MB입니다. 만약 `avg_file_size_mb`가 *10MB 미만*이라면, 이는 StarRocks와 무관하게 스토리지 성능을 저하시키는 원인이 됩니다.
──────────
3. StarRocks FE/BE 주요 메트릭 (모니터링)
Grafana나 Prometheus에서 다음 지표들을 모니터링하십시오.
* starrocks_fe_external_catalog_metadata_request_duration:
* FE가 외부 카탈로그(Iceberg) 메타데이터를 가져오는 데 걸리는 시간입니다. 이 값이 쿼리 시작 시점에 튀고 있다면 Iceberg 메타데이터 자체가 무거운 것입니다.
* starrocks_be_scan_bytes_per_read:
* 한 번의 I/O 읽기 작업 시 읽어오는 데이터 양입니다. Small files 환경에서는 이 수치가 매우 낮게 측정됩니다. (비효율적인 I/O)
──────────
4. 비교 테스트를 통한 검증 (Smoking Gun)
Iceberg 문제임을 확정 짓기 위해 다음 테스트를 수행하고 결과를 비교해 보십시오.
1. Data Compaction 수행:
Iceberg 테이블에 대해 rewrite_data_files 스파크 프로시저 등을 실행하여 파일을 합친 후 동일 쿼리를 수행합니다.
* 결과: 파일 개수가 줄어든 후 쿼리가 비약적으로 빨라진다면, 이는 StarRocks의 문제가 아니라 Iceberg의 데이터 분포 문제입니다.
2. StarRocks Local Table로 복사:
`CREATE TABLE local_test AS SELECT * FROM iceberg_table`로 데이터를 StarRocks 내부로 가져온 뒤 쿼리합니다.
* 결과: 로컬 테이블에서 매우 빠르다면, 병목은 외부 스토리지 읽기(Small Files I/O)에 있음이 증명됩니다.
요약
상대방에게 보여줄 수 있는 가장 강력한 자료는 *`EXPLAIN ANALYZE` 결과에 나타난 수천 개의 `NumFiles`와 그에 대비되는 높은 `FileOpenTime`*입니다. 이는 엔진이 계산을 못 하는 게 아니라, 스토리지에서 데이터를 꺼내오는 입구(Iceberg 파일 구조)가 좁다는 것을 의미합니다.
References
• using_starrocks/External_table_queries.md
• using_starrocks/External_table.md
• data_source/catalog/iceberg_catalog.md
• administration/Query_planning.mdRonJay
09/14/2026, 6:50 AMRocky
09/14/2026, 6:51 AMEXPLAIN 명령어는 상세도에 따라 여러 단계를 제공합니다.
* EXPLAIN COSTS <쿼리>:
• CBO(Cost-based Optimizer)가 계산한 *CPU, Memory, Network 비용 추정치*와 *컬럼별 통계 정보*(Min, Max, Null Count, NDV 등)를 모두 보여줍니다.
• 가장 권장되는 디테일 확인 방법입니다.
* EXPLAIN VERBOSE <쿼리>:
• 논리적/물리적 연산자의 상세 정보(데이터 타입, Null 허용 여부, 구체적인 Join 전략 등)를 포함합니다. 비용 정보보다는 실행 엔진이 어떻게 작동하는지에 초점이 맞춰져 있습니다.
* EXPLAIN ANALYZE <쿼리> (v3.1 이상):
• *실제로 쿼리를 실행*한 뒤, *추정치(Estimate)와 실제 실행 수치(Actual)*를 비교해서 보여줍니다. "왜 비용 계산이 틀렸는지"를 파악할 때 가장 강력한 도구입니다.
──────────
2. 세션 옵션(Variables) 설정
명령어 뒤에 키워드를 붙이는 것 외에, 세션 변수를 통해 출력 내용을 제어할 수 있습니다.
* 통계 정보 상세 노출:
sql
SET show_statistics_item = true;
EXPLAIN COSTS <쿼리>;
이 설정을 켜면 EXPLAIN COSTS 출력 결과 하단에 각 컬럼의 구체적인 통계 메타데이터(통계 수집 시간, 정확도 등)가 추가로 표시되어 CBO가 어떤 데이터를 근거로 비용을 산출했는지 알 수 있습니다.
* 기본 상세도 수준 변경:
sql
-- 기본 EXPLAIN만 쳐도 COSTS 수준으로 나오게 설정 (v3.3+ 기본값)
SET query_detail_explain_level = 'COSTS';
──────────
3. 결과 해석 팁 (무엇을 더 보게 되나?)
`EXPLAIN COSTS`를 사용하면 실행 계획의 각 노드에서 다음 항목을 추가로 확인할 수 있습니다.
* Estimates: {row: 100, cpu: 50.0, memory: 10.0, network: 0.0, cost: 200.5} 와 같이 노드별 소모 자원 추정치가 나옵니다.
* Column Statistics: 각 연산 단계에서 처리되는 컬럼들의 통계치([min, max, null_count, avg_size, ndv])가 표시됩니다. 만약 `ndv`(Number of Distinct Values)가 실제와 크게 다르다면 `ANALYZE TABLE`을 통해 통계를 갱신해야 함을 시사합니다.
요약: 더 깊게 보고 싶을 때의 추천 조합
1. 우선 *`EXPLAIN COSTS <쿼리>`*를 실행합니다.
2. 비용 산출 근거가 의심된다면 *`SET show_statistics_item = true;`*를 켜고 다시 봅니다.
3. 추정치 자체가 실제 데이터와 맞는지 확인하려면 *`EXPLAIN ANALYZE <쿼리>`*를 사용합니다.
References
• sql-reference/sql-statements/cluster-management/plan_profile/EXPLAIN.md
• sql-reference/sql-statements/cluster-management/plan_profile/EXPLAIN_ANALYZE.md
• administration/management/FE_configuration.md
References
• best_practices/query_tuning/query_profile_text_based_analysis.md
• sql-reference/sql-statements/cluster-management/plan_profile/EXPLAIN_ANALYZE.md
• sql-reference/sql-statements/cluster-management/plan_profile/EXPLAIN.md
• best_practices/query_tuning/query_planning.mdRonJay
09/18/2026, 4:58 AMRocky
09/18/2026, 4:58 AMSHOW 명령어 및 관련 방법은 다음과 같습니다.
1. 현재 실행 중인 쿼리 목록 확인 (SHOW PROCESSLIST)
가장 기본적으로 사용하는 명령어로, 현재 어떤 쿼리가 실행 중이며 얼마나 오래 걸리고 있는지 확인합니다.
sql
-- 실행 중인 쿼리 목록 확인
SHOW PROCESSLIST;
-- 전체 SQL 문장을 포함하여 확인
SHOW FULL PROCESSLIST;
* Time: 쿼리가 시작된 후 경과된 시간(초)을 보여줍니다.
* State: 현재 쿼리의 상태(Executing, Pending 등)를 나타냅니다.
──────────
2. 리소스 사용량과 함께 확인 (SHOW RUNNING QUERIES)
StarRocks v3.0 이상에서는 현재 실행 중인 쿼리들의 CPU 및 메모리 사용량을 실시간으로 확인할 수 있습니다.
sql
SHOW RUNNING QUERIES;
* CPU_TIME: 쿼리가 사용한 총 CPU 시간.
* MEMORY_USAGE: 현재 사용 중인 메모리 양.
* 이 명령어를 통해 특정 쿼리가 리소스를 얼마나 점유하며 진행 중인지 파악하기 좋습니다.
──────────
3. 통계 수집 작업 진행도 확인 (SHOW ANALYZE STATUS)
앞서 질문하신 ANALYZE 작업의 진행 상태를 확인할 때 사용합니다.
sql
SHOW ANALYZE STATUS [WHERE TABLE_NAME = '테이블명'];
* STATE: PENDING, RUNNING, FINISHED, FAILED 등의 상태를 보여줍니다.
* PROGRESS: 작업이 어느 정도 완료되었는지 퍼센트(%)나 진행 수치로 확인할 수 있습니다.
──────────
4. 데이터 로딩 작업 확인 (SHOW LOAD)
`INSERT INTO SELECT`나 STREAM LOAD 같은 데이터 적재 작업의 진행률을 볼 때 사용합니다.
sql
SHOW LOAD [FROM 데이터베이스] ORDER BY createtime DESC LIMIT 1;
* Progress: ETL:100%; LOAD:100% 형식으로 단계별 진행률을 보여줍니다.
──────────
5. 더 디테일한 진행 상황을 보는 법 (UI)
SHOW 명령어는 요약된 정보만 제공합니다. 쿼리의 *노드별 진행 단계(예: 100만 건 중 50만 건 처리됨)*를 시각적으로 보려면 다음 방법을 권장합니다.
1. StarRocks Manager (웹 UI): FE 서버 주소(기본 `http://FE_IP:8030`)에 접속하여 Queries 메뉴를 클릭하면 실행 중인 쿼리의 진행률 바(Progress Bar)를 실시간으로 볼 수 있습니다.
2. Query Profile: 쿼리가 완료된 후 또는 실행 중에 get_query_profile 함수나 UI를 통해 각 실행 단계(Scan, Exchange, Join)에서 데이터가 몇 건씩 처리되고 있는지(RowsReturned) 확인할 수 있습니다.
결론: 단순 실행 여부와 시간은 SHOW PROCESSLIST, 리소스 점유율은 SHOW RUNNING QUERIES, 통계 작업은 `SHOW ANALYZE STATUS`를 사용하세요.
References
• sql-reference/sql-statements/cluster-management/plan_profile/SHOW_PROCESSLIST.md
• sql-reference/sql-statements/cbo_stats/SHOW_ANALYZE_STATUS.md
• sql-reference/sql-statements/cluster-management/plan_profile/SHOW_RUNNING_QUERIES.md
• administration/Query_planning.mdRonJay
09/18/2026, 5:00 AMRocky
09/18/2026, 5:00 AMRunning 상태로 머물러 있다면, 실제로 데이터를 처리 중인지 아니면 특정 단계에서 멈춰 있는지를 확인해야 합니다.
다음 단계별 방법으로 쿼리의 *내부 진행 상황*을 파악할 수 있습니다.
──────────
1. `get_query_profile()`로 실시간 진행률 확인 (권장)
StarRocks v3.0 이상에서는 *실행 중인 쿼리*의 프로파일을 즉시 조회하여 각 연산자(Operator)가 현재 데이터를 몇 건이나 처리했는지 확인할 수 있습니다.
1. `SHOW RUNNING QUERIES`에서 해당 쿼리의 *`QueryId`*를 복사합니다.
2. 다음 쿼리를 실행합니다.
sql
SELECT get_query_profile('복사한_QueryId');
3. 확인할 지표:
* RowsReturned: 특정 노드(예: IcebergScanNode)에서 숫자가 계속 올라가고 있다면 정상적으로 읽는 중입니다. 숫자가 멈춰 있다면 해당 파일 I/O에서 병목이 걸린 것입니다.
* ActiveTime: 연산자가 활성화된 시간입니다.
──────────
2. FE 웹 UI에서 시각적으로 확인
텍스트보다 직관적으로 어느 단계에서 막혔는지 볼 수 있습니다.
1. 브라우저에서 StarRocks FE 주소로 접속합니다 (http://<FE_IP>:8030).
2. 상단 메뉴의 [Queries] 탭을 클릭합니다.
3. 현재 실행 중인 쿼리 목록에서 해당 쿼리의 [Profile] 링크를 클릭합니다.
4. *Graph view*를 통해 어느 연산자(Scan, Join, Aggregate 등)에서 데이터 흐름이 멈춰 있는지, 또는 어느 BE(Backend) 노드가 느린지 한눈에 확인할 수 있습니다.
──────────
3. `SHOW PROCESSLIST`의 상세 상태 확인
`SHOW PROCESSLIST`는 쿼리의 가장 바깥쪽 상태를 보여줍니다.
sql
SHOW FULL PROCESSLIST;
* State: `Executing`인지, 아니면 리소스를 기다리는 `Pending`인지 확인하세요.
* Time: 현재까지 소요된 초 단위 시간입니다. 만약 시간이 수천 초인데 `RowsReturned`가 0이라면 메타데이터를 가져오는 단계(Planning)에서 Iceberg Manifest 파일을 읽느라 고전하고 있을 가능성이 큽니다.
──────────
4. BE(Worker)의 상태 확인
쿼리 문제가 아니라 서버 문제일 수도 있습니다.
sql
SHOW BACKENDS;
* Alive: 모든 BE가 `true`인지 확인하세요. 하나라도 `false`라면 해당 노드에서 담당하던 태스크가 타임아웃될 때까지 쿼리가 멈춰 있을 수 있습니다.
* MemUsed / CPU: 특정 BE의 메모리가 꽉 찼거나 CPU가 100%라면 그 노드가 전체 쿼리의 발목을 잡고 있을 수 있습니다.
──────────
5. Iceberg Small Files 이슈와 연결하여 해석하기
질문하신 상황(Small Files 문제)이라면, 프로파일에서 다음과 같은 특징이 나타날 것입니다.
* *`IcebergScanNode`*에서 *`NumFiles`*는 매우 큰데 *`RowsRead`*가 아주 천천히 올라감.
* FileOpenTime 수치가 계속 증가함.
* *`PeakMemoryUsage`*는 낮은데 *`Time`*만 계속 흐름 (CPU 연산보다 I/O 대기가 길기 때문).
결론: 지금 바로 `SELECT get_query_profile('쿼리ID');`를 실행하여 RowsReturned 수치가 변하고 있는지 확인해 보시기 바랍니다. 수치가 변하지 않는다면 Iceberg 메타데이터 스캔 단계에서 멈춘 것이고, 수치가 아주 느리게 변한다면 Small Files로 인한 I/O 병목입니다.
References
• sql-reference/sql-statements/cluster-management/plan_profile/SHOW_RUNNING_QUERIES.md
• sql-reference/sql-statements/cluster-management/plan_profile/SHOW_PROCESSLIST.md
• administration/Query_planning.md
• sql-reference/sql-functions/utility-functions/get_query_profile.md입니다.get_query_profile) (Note: verify specific function availability in your version)RonJay
09/18/2026, 5:03 AMRocky
09/18/2026, 5:03 AMjdbc_connection_pool_size (기본값: 8)
* *각 BE 노드에서 동일한 `jdbc_url`을 사용하는 쿼리들이 공유하는 최대 커넥션 수*입니다.
* 예를 들어 BE가 3대이고 이 값이 8이면, 전체 클러스터에서는 해당 JDBC Catalog에 대해 최대 24개의 커넥션이 생성될 수 있습니다.
* jdbc_minimum_idle_connections (기본값: 1)
* 풀에서 유지하는 최소 유휴(Idle) 커넥션 수입니다.
* jdbc_connection_timeout_ms (기본값: 10,000ms / 10초)
* 커넥션 풀에서 커넥션을 획득하기 위해 대기하는 최대 시간입니다. 이 시간을 초과하면 쿼리가 실패합니다. (v3.1.5+ 등 최신 버전 기준)
2. 커넥션 생명주기 관리
커넥션이 좀비 상태가 되거나 타겟 DB에서 끊기는 것을 방지하기 위한 설정입니다.
* jdbc_connection_max_lifetime_ms (기본값: 300,000ms / 5분)
* 커넥션의 최대 수명입니다. 이 시간이 지나면 커넥션은 폐기되고 새로 생성됩니다. 타겟 DB(MySQL, PostgreSQL 등)의 wait_timeout 설정보다 짧게 설정하는 것이 권장됩니다. (최소 허용치: 30,000ms)
* jdbc_connection_idle_timeout_ms (기본값: 600,000ms / 10분)
* 커넥션이 유휴 상태로 머물 수 있는 최대 시간입니다.
3. 설정 방법
이 설정들은 *FE와 BE 모두*에서 설정할 수 있으며, 일반적으로 동일하게 맞추어 주는 것이 좋습니다.
* BE 설정 (be.conf 수정 또는 동적 변경):
데이터 스캔 시 BE에서 커넥션을 사용하므로 실제 쿼리 성능과 직결됩니다.
shell
# be.conf 예시
jdbc_connection_pool_size = 16
* FE 설정 (fe.conf 수정 또는 동적 변경):
Metadata 조회(Table Schema 확인 등) 시 FE에서 사용하는 커넥션 풀을 제어합니다.
sql
-- 동적 변경 예시 (관리자 권한 필요)
ADMIN SET FRONTEND CONFIG ("jdbc_connection_pool_size" = "16");
요약 및 권장사항
1. 공유 범위: 커넥션 풀은 "BE 노드 단위" 및 "JDBC URL 단위"로 관리됩니다.
2. 동시성: 동시 쿼리가 많아 Connection is not available 에러가 발생한다면 `jdbc_connection_pool_size`를 늘려야 합니다.
3. 안정성: 외부 DB의 커넥션 타임아웃 설정을 확인하고, StarRocks의 `jdbc_connection_max_lifetime_ms`를 그보다 짧게 설정하여 끊긴 커넥션을 참조하는 일을 방지하세요.
References
• administration/management/FE_configuration.md
• administration/management/BE_configuration.md
• data_source/catalog/jdbc_catalog.md
References
• administration/management/FE_configuration.md
• administration/management/BE_configuration.md
• data_source/catalog/jdbc_catalog.mdRonJay
09/18/2026, 5:27 AMRocky
09/18/2026, 5:27 AMjdbc_connection_pool_size: 각 BE 노드당 생성할 수 있는 최대 커넥션 수입니다. (기본값: 8)
* 주의: 전체 커넥션 수 = BE 노드 수 * jdbc_connection_pool_size 입니다. Oracle의 SESSIONS 또는 PROCESSES 설정값보다 작게 유지되도록 계산해야 합니다.
* jdbc_connection_max_lifetime_ms: 커넥션의 최대 수명입니다. (기본값: 300,000ms / 5분)
* Oracle 측의 IDLE_TIMEOUT 보다 약간 짧게 설정하여, Oracle이 커넥션을 강제로 끊기 전에 StarRocks가 먼저 안전하게 회수하도록 설정하는 것이 좋습니다.
* jdbc_connection_idle_timeout_ms: 사용되지 않는 커넥션을 풀에서 제거하는 대기 시간입니다.
2. 쿼리 동시성 및 리소스 격리 (Resource Group)
가장 강력한 보호 방법입니다. Oracle을 사용하는 쿼리들만 별도의 *Resource Group*으로 묶어 동시 실행 수와 리소스 사용량을 제한할 수 있습니다.
* 동시성 제한 (concurrency_limit):
sql
CREATE RESOURCE GROUP oracle_protection_group
TO (db='oracle_catalog_db') -- 특정 DB(Catalog) 접속 시 적용
WITH (
"concurrency_limit" = "5", -- Oracle로 동시에 나가는 쿼리를 5개로 제한
"cpu_weight" = "10",
"mem_limit" = "20%"
);
* 폭주 쿼리 차단 (Big Query Limits): Oracle에서 너무 많은 로우를 읽거나 CPU를 과다하게 점유하는 쿼리를 자동으로 종료시킵니다.
* `big_query_scan_rows_limit`: 한 쿼리가 스캔할 수 있는 최대 로우 수.
* `big_query_cpu_second_limit`: 한 쿼리가 사용할 수 있는 최대 CPU 시간.
3. 스캔 및 병렬도 제어 (Scan Concurrency)
StarRocks는 하나의 쿼리를 여러 개의 스캔 태스크로 쪼개서 병렬 처리합니다. 너무 높은 병렬도는 Oracle에 순간적인 부하를 줄 수 있습니다.
* is_unpartitioned_column_with_range (v3.2.9+ Oracle 지원): Oracle 테이블의 통계 정보를 바탕으로 데이터를 범위를 나누어 병렬 스캔할지 여부를 결정합니다. 부하가 걱정된다면 이 기능을 조절하여 병렬도를 낮출 수 있습니다.
* JDBC URI 파라미터: jdbc_uri 설정 시 Oracle 전용 옵션(예: defaultRowPrefetch 등)을 추가하여 Fetch 사이즈를 조절함으로써 네트워크와 Oracle CPU 부하를 튜닝할 수 있습니다.
4. 메타데이터 조회 최적화
StarRocks가 Oracle의 메타데이터(테이블 구조 등)를 너무 자주 조회하지 않도록 보호합니다.
* Deferred JDBC REMARKS fetching: v3.5/4.x 버전에서는 테이블 목록 조회 시 코멘트(Remarks) 정보 등을 나중에 가져오도록 최적화되어 Oracle의 시스템 딕셔너리(Dictionary) 부하를 줄여줍니다.
* Metadata Caching: Catalog 생성 시 메타데이터 캐시 관련 속성을 설정하여 반복적인 메타데이터 조회를 방지합니다.
5. 아키텍처적 보호 (Materialized View)
실시간성이 아주 중요하지 않다면, Oracle을 직접 쿼리하는 대신 *Asynchronous Materialized View (Async MV)*를 사용하세요.
* 효과: Oracle 데이터의 스냅샷을 StarRocks 내부에 저장합니다. 사용자는 StarRocks 내부 데이터를 쿼리하므로 Oracle에는 전혀 부하가 가지 않으며, 정해진 주기(예: 1시간마다)에만 Oracle에 접속하여 데이터를 갱신합니다.
4.1.1 기준 권장 설정 요약
1. Oracle 세션 수 보호: `BE 대수 * 8`이 Oracle 허용 세션보다 큰지 확인하고, 필요 시 `jdbc_connection_pool_size`를 낮추세요.
2. Resource Group 적용: Oracle 전용 유저나 DB를 Classifier로 지정하여 `concurrency_limit`을 반드시 설정하세요.
3. Timeout 설정: `jdbc_connection_max_lifetime_ms`를 Oracle의 세션 타임아웃보다 짧게 설정하세요.
References
• data_source/catalog/jdbc_catalog.md
• administration/management/resource_management/resource_group.md
• administration/management/BE_configuration.md (jdbc_connection_pool_size 관련)
References
• administration/management/resource_management/resource_group.mdRonJay
09/21/2026, 1:29 AMRocky
09/21/2026, 1:29 AMRunning 상태라면, 리소스 부족보다는 I/O 대기(스캔), 메타데이터 로딩, 또는 외부 카탈로그 대기 중일 가능성이 높습니다.
실행 중인 쿼리의 상세 상태(예: 스캔 중인지, 어느 노드에서 멈춰 있는지)를 확인하는 3가지 핵심 방법을 안내해 드립니다.
1. SHOW PROC '/global_current_queries' (가장 빠른 요약 확인)
실시간으로 어떤 쿼리가 돌고 있는지, 그리고 그 쿼리가 데이터를 얼마나 읽었는지(ScanRows, ScanBytes) 한눈에 볼 수 있습니다.
sql
SHOW PROC '/global_current_queries';
* ScanRows / ScanBytes: 이 수치가 계속 올라가고 있다면 현재 디스크나 외부 저장소(S3, HDFS 등)에서 데이터를 열심히 읽고 있는 중입니다.
* CPUTime: CPU를 얼마나 썼는지 보여줍니다. `ExecTime`은 긴데 `CPUTime`이 매우 낮다면, 연산보다는 네트워크/디스크 I/O를 기다리는 "상태"입니다.
* MemoryUsage: 현재 쿼리가 점유 중인 메모리 양을 확인할 수 있습니다.
2. `ANALYZE PROFILE`로 실시간 진행률 확인 (심층 분석)
StarRocks v3.1 이상이라면 실행 중인 쿼리의 *연산자별 상태*를 시각적으로(텍스트 형태) 확인할 수 있습니다.
1. 먼저 `QueryId`를 확인합니다.
2. 다음 명령어를 실행합니다.
sql
ANALYZE PROFILE FROM '복사한_QueryId';
* 아이콘 확인:
* 🚀 (로켓): 현재 해당 연산자(Operator)가 실행 중임.
* ✅ (체크): 해당 단계가 완료됨.
* ⏳ (모래시계): 앞선 단계가 끝나기를 기다리는 중.
* ScanNode 확인: 만약 `OlapScanNode`나 IcebergScanNode 옆에 🚀 아이콘이 있고 `RowsRead`가 천천히 올라가고 있다면, 파일 스캔 단계에서 병목이 발생한 것입니다.
3. FE 웹 UI (시각적 확인)
텍스트보다 직관적으로 보고 싶을 때 가장 좋습니다.
1. 웹 브라우저에서 `http//<FE IP>8030`에 접속합니다.
2. 상단 [Queries] 메뉴를 클릭합니다.
3. Running Queries 목록에서 해당 쿼리의 *[Profile]*을 클릭합니다.
4. Graph 탭을 보면 전체 쿼리 실행 계획(Plan) 트리에서 어느 노드(Scan, Join, Aggregate 등)가 활성화되어 있는지, 어느 BE 노드에서 정체가 발생하는지 색깔과 수치로 바로 확인 가능합니다.
쿼리가 멈춘 것처럼 보일 때 체크포인트
* ScanRows가 0이고 변화 없음: 쿼리 플래닝(Planning) 단계에서 메타데이터를 가져오느라 고전하고 있거나, 외부 카탈로그(Oracle, Hive 등)의 응답을 기다리는 상태일 수 있습니다.
* ScanRows는 올라가는데 속도가 매우 느림: 작은 파일(Small Files)이 너무 많아서 파일을 하나하나 여는 데 시간이 다 소요되고 있을 가능성이 큽니다.
* State가 PENDING임: `SHOW RUNNING QUERIES`에서 상태가 `PENDING`이라면, 리소스 그룹(Resource Group) 설정에 의해 큐에 대기 중인 상태입니다.
References
• using_starrocks/running_queries.md
• best_practices/query_tuning/query_profile_text_based_analysis.md
• administration/management/monitor_manage_big_queries.md
References
• using_starrocks/running_queries.md
• administration/management/resource_management/query_queues.md
• administration/management/monitor_manage_big_queries.mdRonJay
09/21/2026, 1:33 AMRocky
09/21/2026, 1:33 AMWHERE, JOIN, GROUP BY, DISTINCT 등에 사용된 컬럼을 자동으로 식별하여 `_statistics_.predicate_columns`라는 시스템 테이블에 Insert 합니다. 이를 통해 어떤 컬럼이 "중요한 컬럼(Predicate Column)"인지 기록합니다.
* 효과: 자동 통계 수집 시, 전체 컬럼이 아닌 이 테이블에 등록된 *Predicate Column들에 대해서만 우선적으로 정밀 수집(Full Collection)*을 수행하여 옵티마이저의 정확도는 유지하면서 수집 부하를 획기적으로 줄입니다.
* Delete 하는 이유: 더 이상 쿼리에 사용되지 않거나, 만료된 통계 컬럼 정보를 정리하기 위해 내부적으로 관리 프로세스가 Delete 작업을 수행할 수 있습니다.
2. Primary Key 테이블의 내부 전략 (Delete+Insert)
Primary Key 테이블에서 특정 컬럼을 조건(merge_condition)으로 업데이트할 때 발생하는 메커니즘입니다.
* 내부 전략: StarRocks의 Primary Key 테이블은 기본적으로 Delete+Insert 전략을 사용합니다. 즉, 기존 데이터를 삭제 마킹(Delete)하고 새로운 데이터를 추가(Insert)하는 방식입니다.
* Predicate Column(조건 열)의 역할: 업데이트 시 merge_condition (예: version 컬럼 등)을 설정하면, StarRocks는 이 컬럼의 값을 비교하여 조건에 맞을 때만 기존 로우를 *Delete*하고 새 로우를 Insert 합니다.
* 하는 이유: 실시간으로 발생하는 데이터 순서 뒤바뀜(Out-of-order) 문제를 해결하기 위함입니다. 조건 열의 값이 기존보다 클 때만 삭제 후 삽입을 수행함으로써, 최신 데이터가 과거 데이터에 의해 덮어씌워지는 것을 방지합니다.
요약
사용자가 시스템 로그나 메타데이터 테이블에서 `predicate_columns`에 대한 Insert/Delete를 보셨다면, 이는 *StarRocks가 성능 최적화를 위해 "어떤 컬럼이 쿼리에 자주 쓰이는지"를 스스로 학습하고 관리하는 과정*이라고 이해하시면 됩니다. (CBO 통계 수집 최적화)
관련 설정 및 확인:
* _statistics_.predicate_columns 테이블 조회 시 현재 관리되는 컬럼 확인 가능
* FE 설정 중 enable_collect_full_statistic 등의 옵션으로 통계 수집 방식 제어 가능
References
• using_starrocks/Cost_based_optimizer.md
• loading/Load_to_Primary_Key_tables.md
• table_design/table_types/primary_key_table.md
References
• using_starrocks/Cost_based_optimizer.md
• table_design/table_types/primary_key_table.md
• loading/Load_to_Primary_Key_tables.md
References
• loading/Load_to_Primary_Key_tables.md
• sql-reference/sql-statements/table_bucket_part_index/UPDATE.md
• using_starrocks/Cost_based_optimizer.mdRonJay
09/21/2026, 1:41 AMRocky
09/21/2026, 1:42 AMResultSink 연산자 지표 확인 (Profile 분석)
가장 확실한 방법은 해당 쿼리의 Profile을 열어 ResultSink 또는 *`ResultSinkOperator`*의 메트릭을 확인하는 것입니다.
* 확인 방법: ANALYZE PROFILE FROM 'QueryID'; 실행
* 주요 체크 포인트:
* RowsRead vs RowsReturned: CN이 읽어들인 행 수와 실제로 FE로 보낸 행 수가 일치하는지 확인합니다.
* SerializeChunkTime: 결과를 FE로 보내기 위해 직렬화하는 데 시간이 너무 오래 걸리지 않는지 확인합니다.
* RpcAvgTime / RpcCount: FE로 데이터를 보낼 때 발생한 네트워크 통신(RPC) 속도를 확인합니다. 만약 이 시간이 길다면 네트워크 대역폭 문제나 FE의 수신 부하를 의심해야 합니다.
2. FE의 상태 및 메모리 확인
CN은 결과를 준비했지만, FE가 이를 받아줄 여력이 없을 때 결과 전달이 멈춥니다.
* FE Full GC: FE가 대용량 결과셋을 받다가 메모리가 부족해져 Full GC에 빠지면, CN으로부터 오는 RPC 요청을 처리하지 못합니다. `fe.gc.log`를 확인하여 쿼리 종료 시점에 GC 정체가 있었는지 보세요.
* MySQL 클라이언트 대기: FE는 CN으로부터 받은 데이터를 MySQL 프로토콜을 통해 클라이언트(User)에게 전달합니다. 만약 클라이언트가 데이터를 천천히 읽어가면(Socket Buffer 가득 참), FE도 CN의 데이터를 더 이상 받지 못하고 대기하게 됩니다.
3. 결과셋 크기 및 타임아웃
* 대용량 결과셋: `SELECT *`와 같이 수백만 건 이상의 로우를 반환하는 경우, CN의 연산 시간보다 FE로 데이터를 전송하고 수집하는 시간이 훨씬 길어질 수 있습니다.
* query_timeout: CN에서는 연산이 끝났어도 전체 쿼리 타임아웃(query_timeout 기본 300초) 이내에 FE가 모든 데이터를 클라이언트에게 전송 완료하지 못하면 쿼리는 실패(Cancelled) 처리됩니다.
4. 네트워크 설정 (brpc)
드문 경우지만, CN과 FE 사이의 RPC 연결 설정 문제로 인해 전송이 끊길 수 있습니다.
* brpc_connection_type: 네트워크 지연이 잦다면 BE/CN 설정에서 이 값을 `pooled`로 설정하여 연결 효율을 높일 수 있습니다.
* FE/CN 로그 확인: `fe.warn.log`나 `cn.warn.log`에서 RPC error, connection closed 또는 ResultSink 관련 경고 문구가 있는지 확인하십시오.
요약 및 조치
1. 결과가 정말 누락되었는가?: StarRocks는 분산 환경에서 일부 데이터만 반환하지 않습니다. 성공하면 전체가 반환되고, 문제가 있으면 에러가 발생합니다. 아무 결과 없이 쿼리가 끝났다면 WHERE 조건에 의해 실제 결과가 0건인 경우가 많습니다.
2. 지연 상황인가?: `SHOW PROC '/global_current_queries'`를 통해 해당 쿼리의 `ScanRows`는 멈췄는데 `CPUTime`이나 `ExecTime`만 늘어나고 있다면 전송/수집 병목입니다.
3. 해결책: 결과셋이 너무 크다면 `LIMIT`을 사용하거나, `INSERT INTO SELECT`를 통해 StarRocks 내부 테이블에 먼저 저장하는 방식을 권장합니다.
References
• best_practices/query_tuning/query_profile_operator_metrics.md
• faq/Sql_faq.md
• introduction/Architecture.md
References
• faq/Sql_faq.md
• data_source/data_cache_troubleshooting.md
• knowledge/trouble_shooting/fe_deadlock_problems.md
• release_notes/release-2.0.mdRonJay
09/21/2026, 2:32 AMRocky
09/21/2026, 2:32 AMenable_statistic_collect = false 설정은 *통계 정보를 실제로 수집하는 "Analyze Job"(백그라운드 계산 작업)을 중지*할 뿐, 어떤 컬럼이 쿼리에 사용되었는지 기록하거나 로딩 이력을 관리하는 *메타데이터 기록 행위 자체를 완전히 막지는 않기 때문*입니다.
해당 작업들이 계속 실행되는 상세 이유와 완전히 끄는 방법은 다음과 같습니다.
1. `predicate_columns`에 Insert가 발생하는 이유
StarRocks v3.5 이상에서는 효율적인 통계 수집을 위해 "어떤 컬럼이 필터(WHERE)나 조인에 자주 쓰이는가"를 실시간으로 학습합니다.
* 이유: 나중에 통계 수집을 다시 켤 때, 모든 컬럼을 다 조사하는 대신 이 테이블에 기록된 '주요 컬럼'들만 골라서 수집하기 위한 기초 데이터를 쌓는 과정입니다.
* 중단 방법: 이 기록 행위 자체를 끄려면 아래 FE 설정을 `false`로 바꿔야 합니다.
sql
-- FE 설정 변경 (ADMIN SET CONFIG)
ADMIN SET FRONTEND CONFIG ("enable_predicate_columns_collection" = "false");
2. `loads_history`에 Insert가 발생하는 이유
이 테이블은 단순히 통계 수집용이 아니라, *시스템의 전체적인 데이터 로딩 이력(Broker Load, Stream Load, Insert 등)을 기록하는 모니터링 테이블*입니다.
* 이유: 사용자가 `SHOW LOAD`를 실행하거나 `information_schema.loads`를 조회할 때 보여줄 과거 데이터를 저장하기 위해 시스템이 주기적으로 메모리의 로딩 정보를 이 테이블로 옮겨 담습니다.
* 참고: 이 작업은 통계 수집 활성화 여부와 상관없이 시스템 운영 및 감사(Auditing)를 위해 기본적으로 수행되는 백그라운드 작업입니다. (보통 부하가 매우 적습니다.)
3. 추가로 체크할 설정
만약 INSERT INTO ... SELECT 같은 DML 수행 직후에 자동으로 통계가 도는 것을 막고 싶다면 다음 옵션도 확인해 보시기 바랍니다.
* 첫 로드 시 자동 수집 방지:
sql
ADMIN SET FRONTEND CONFIG ("enable_statistic_collect_on_first_load" = "false");
요약
* `enable_statistic_collect`: 실제로 데이터를 읽어서 통계치를 계산하는 *무거운 작업*을 끔.
* `enable_predicate_columns_collection`: 쿼리 시점에 "이 컬럼이 쓰였다"라고 *메타데이터에 기록하는 가벼운 작업*을 끔.
만약 클러스터 리소스를 조금이라도 더 아끼고 싶다면 `enable_predicate_columns_collection`까지 꺼주시면 됩니다.
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• loading/loading_introduction/troubleshooting_loading.md
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• loading/loading_introduction/troubleshooting_loading.md
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• faq/Sql_faq.mdRonJay
09/21/2026, 2:37 AMRocky
09/21/2026, 2:37 AMenable_statistic_collect)과 predicate_columns 수집을 끄는 것은 리소스 절약 측면에서 합리적인 전략이 될 수 있습니다.
하지만 무조건 끄기 전에 고려해야 할 *성능상 실(失)과 득(得)*이 있습니다. 상황에 맞는 전략을 선택하시는 데 도움이 되도록 상세히 정리해 드립니다.
1. 옵션을 꺼도 괜찮은 경우 (전략적 '득')
* Iceberg 통계가 최신인 경우: Spark, Flink 등 데이터 생성 단계에서 Iceberg 테이블의 NDV, NULL COUNT, MIN/MAX 등의 통계 정보가 Puffin 파일이나 Manifest에 정확히 기록되고 있다면, StarRocks 옵티마이저는 이 정보를 직접 읽어서 쿼리 계획을 세울 수 있습니다.
* 리소스 부하 최소화: 외부 테이블(External Catalog)에 대한 통계 수집은 결국 BE(Compute Node)가 데이터를 다시 읽어야 하는 작업입니다. 이를 끄면 백그라운드 I/O와 CPU 사용량을 줄일 수 있습니다.
* 데이터 업데이트가 너무 빈번할 때: 데이터가 너무 자주 바뀌어 StarRocks가 통계를 수집하는 속도보다 데이터 변경 속도가 빠르다면, 차라리 원천(Iceberg)의 메타데이터 통계에 의존하는 것이 더 효율적입니다.
2. 옵션을 켜두는 것이 좋은 경우 (전략적 '실')
* 더 정밀한 통계가 필요할 때 (Histogram 등): Iceberg 메타데이터는 기본적인 컬럼 통계는 제공하지만, 데이터 분포를 나타내는 히스토그램(Histogram) 정보 등은 StarRocks가 직접 `ANALYZE`를 수행했을 때 훨씬 정밀하게 생성됩니다. 복잡한 Join이나 대규모 집계 쿼리가 많다면 StarRocks 내부 통계가 있는 것이 훨씬 유리합니다.
* CBO의 응답 속도: Iceberg 메타데이터를 매번 원격 저장소(S3/HDFS)에서 읽어오는 것보다, StarRocks 내부 시스템 테이블(_statistics_)에 캐싱된 통계 정보를 읽는 것이 쿼리 최적화(Planning) 단계에서 더 빠릅니다.
* Predicate Column의 효율성: predicate_columns 수집은 무거운 작업이 아닙니다. 이 정보를 켜두면 나중에 특정 테이블만 성능이 안 나와서 수동으로 `ANALYZE`를 실행할 때, 어떤 컬럼을 우선적으로 수집해야 할지 알려주는 이정표가 됩니다.
3. 권장하는 운영 전략
전략 A: 리소스 최적화형 (External Catalog 의존)
Iceberg 통계를 신뢰하고 StarRocks의 부하를 줄이고 싶다면 아래와 같이 설정합니다.
sql
-- 1. 전역 자동 통계 수집 중지
ADMIN SET FRONTEND CONFIG ("enable_statistic_collect" = "false");
-- 2. 쿼리 기반 자동 수집(v3.4+) 중지
SET GLOBAL enable_query_trigger_analyze = false;
-- 3. 불필요한 메타 기록 중지
ADMIN SET FRONTEND CONFIG ("enable_predicate_columns_collection" = "false");
전략 B: 하이브리드형 (권장)
중요도가 낮은 테이블은 Iceberg 통계를 그대로 쓰고, *성능이 중요한 핵심 테이블만 StarRocks에서 수동으로 `ANALYZE`*를 수행합니다.
* 자동 수집은 끄되(enable_statistic_collect = false),
* predicate_columns 수집은 켜두어 어떤 컬럼이 중요한지 파악합니다.
* 쿼리 속도가 느린 특정 Iceberg 테이블에 대해서만 `ANALYZE TABLE iceberg_catalog.db.table`을 실행하여 StarRocks 내부에 고정밀 통계를 생성합니다.
요약
이미 Iceberg 쪽에 완벽한 통계가 있다면 끄는 것이 전략적으로 맞습니다. 다만, StarRocks에서 실행하는 쿼리 중 Join이 복잡하거나 데이터 분포가 고르지 않아 성능 최적화가 극도로 중요한 경우에는 StarRocks의 내부 통계 수집 기능을 활용하는 것이 쿼리 성능 면에서 더 우수할 수 있습니다.
References
• using_starrocks/Cost_based_optimizer.md
• data_source/catalog/iceberg/iceberg_catalog.md
• administration/management/FE_configuration.md
References
• using_starrocks/Cost_based_optimizer.md
• data_source/catalog/iceberg/iceberg_catalog.mdRonJay
09/21/2026, 2:51 AMsql
-- 1. 전역 자동 통계 수집 중지
ADMIN SET FRONTEND CONFIG ("enable_statistic_collect" = "false");
-- 2. 쿼리 기반 자동 수집(v3.4+) 중지
SET GLOBAL enable_query_trigger_analyze = false;
-- 3. 불필요한 메타 기록 중지
ADMIN SET FRONTEND CONFIG ("enable_predicate_columns_collection" = "false");
ui query 탭에서 계속 isert intor statistics loads_history랑 delete from statistics predicate columns 가 실행되고 있는게 보여, 제대로 설정이 안된건가? (4.1.1 버전임)Rocky
09/21/2026, 2:51 AMAnalyze)과는 무관합니다. 굳이 주기를 늘리고 싶다면 FE 설정에서 loads_history_sync_interval_second 값을 조절할 수 있지만 권장하지 않습니다.
2. `DELETE FROM statistics.predicate_columns`가 계속 뜨는 이유
이것은 수집이 아니라 가비지 컬렉션(GC, 데이터 삭제) 작업입니다.
* 역할: 설정하신 대로 `enable_predicate_columns_collection`을 `false`로 바꾸면 더 이상 새로운 컬럼 정보는 쌓이지 않습니다. 하지만 *기존에 쌓여있던 오래된 데이터*는 시스템 테이블의 크기를 줄이기 위해 백그라운드에서 주기적으로 지워야 합니다.
* 상황: 현재 UI에서 보이는 `DELETE`는 시스템 클리너(TableKeeper/StatisticCleaner)가 유효기간(TTL)이 지난 과거 기록들을 삭제하고 있는 모습입니다. 테이블이 완전히 비워지면 더 이상 큰 의미가 없는 작업이 됩니다.
3. 설정이 잘 되었는지 확인하는 확실한 방법
UI에 뜨는 SQL이 아니라, 실제 *통계 수집 작업(Analyze Job)*이 생성되는지를 확인해야 합니다. 아래 명령어를 실행했을 때 새로운 작업이 생기지 않는다면 설정이 완벽히 적용된 것입니다.
sql
-- 최근에 실행된 통계 수집 작업이 있는지 확인 (Status가 RUNNING인 것이 없어야 함)
SHOW ANALYZE STATUS;
-- 예약된 자동 수집 작업이 있는지 확인
SHOW ANALYZE JOB;
요약
* 보여지는 쿼리들은 *"통계를 계산하는 무거운 쿼리"*가 아니라, *"시스템 테이블을 청소하고 로그를 남기는 가벼운 관리용 쿼리"*입니다.
* v4.1.1 버전에서도 위 3가지 설정을 하셨다면 외부 테이블(Iceberg 등)을 읽어서 통계를 만드는 무거운 연산은 발생하지 않으니 안심하셔도 됩니다.
* 만약 UI가 지저분해 보이는 것이 문제라면, UI 필터에서 User: root 또는 시스템 사용자를 제외하고 보시는 것을 권장합니다.
References
• administration/management/FE_configuration.md
• using_starrocks/Cost_based_optimizer.md
• loading/loading_introduction/troubleshooting_loading.md
References
• using_starrocks/Cost_based_optimizer.mdRonJay
09/21/2026, 5:12 AMRocky
09/21/2026, 5:12 AMsql
ALTER SYSTEM ADD FOLLOWER "새노드IP:9010";
* Observer로 추가할 경우:
sql
ALTER SYSTEM ADD OBSERVER "새노드IP:9010";
2. 새 노드의 메타데이터 디렉토리 초기화
이전의 잘못된 시작 시도로 인해 새 노드의 meta 디렉토리에 잘못된 클러스터 정보가 기록되었을 수 있습니다. 새 노드에서 해당 디렉토리를 비워줍니다.
bash
# fe/conf/fe.conf 에 정의된 meta_dir 경로 확인 (기본값은 fe/meta)
rm -rf /path/to/fe/meta/*
3. 새 노드 시작
이제 --helper 옵션을 사용하여 리더 노드 정보를 알려주며 시작합니다.
bash
./bin/start_fe.sh --helper 리더IP:9010 --daemon
주의사항 및 체크리스트
* IP 일치 확인: ALTER SYSTEM ADD 명령에 입력한 IP와 새 노드의 fe.conf 내 priority_networks 설정에 의해 결정되는 IP가 정확히 일치해야 합니다. (일치하지 않으면 다른 노드로 인식하여 거부됩니다.)
* 방화벽: 노드 간 `edit_log_port`(9010) 및 `rpc_port`(9020) 통신이 열려 있는지 확인하세요.
* 상태 확인: 등록 후 리더 노드에서 SHOW FRONTENDS; 명령을 통해 새 노드의 Alive 상태가 `true`가 되는지 확인하세요.
만약 이미 `ALTER SYSTEM ADD`를 했는데도 이 에러가 난다면, `fe.conf`의 priority_networks 설정이 잘못되어 새 노드가 엉뚱한 IP로 부팅되고 있는 것은 아닌지 `fe.log`를 다시 확인해 보시기 바랍니다.
References
• administration/Meta_recovery.md
• faq/Deploy_faq.md
• deployment/Deploy_shared_nothing_manually.md
• sql-reference/sql-statements/cluster-management/ALTER_SYSTEM.md
References
• administration/Meta_recovery.md
• faq/Deploy_faq.md
• deployment/Deploy_shared_nothing_manually.md
• sql-reference/sql-statements/cluster-management/ALTER_SYSTEM.md
References
• administration/Meta_recovery.md
• faq/Deploy_faq.md
• deployment/Deploy_shared_nothing_manually.md
• sql-reference/sql-statements/cluster-management/ALTER_SYSTEM.md
References
• faq/Deploy_faq.md
• administration/Meta_recovery.mdRonJay
09/21/2026, 5:14 AMRocky
09/21/2026, 5:15 AMFE with the same host : already exists 에러는 추가하려는 FE의 IP(또는 Hostname)와 Port 조합이 이미 StarRocks 메타데이터에 등록되어 있을 때 발생합니다.
이 상황은 보통 다음 두 가지 경우 중 하나입니다.
1. 이미 등록된 노드인 경우 (가장 흔한 케이스)
이미 ALTER SYSTEM ADD FOLLOWER/OBSERVER 명령을 한 번 실행하셨을 가능성이 큽니다. StarRocks는 한 번 등록된 노드 정보를 계속 가지고 있습니다.
* 확인 방법: 리더 FE에 접속하여 아래 명령을 실행하세요.
sql
SHOW FRONTENDS; -- 또는 SHOW PROC '/frontends';
* 해결책: 목록에 해당 IP가 이미 있다면, ALTER SYSTEM ADD 명령을 다시 실행할 필요가 없습니다. 바로 새 노드 서버로 가서 FE 프로세스만 시작하면 됩니다.
bash
# (이미 meta가 생성되었다면 삭제 후)
./bin/start_fe.sh --helper <리더IP>:9010 --daemon
2. 이전 노드의 잔재가 남은 경우 (재설치 시)
이전에 같은 IP로 FE를 운영하다가 정상적으로 DROP 하지 않고 프로세스만 껐을 경우, 메타데이터에는 여전히 해당 노드가 남아 있습니다.
* 해결책: 기존 정보를 지우고 다시 등록하고 싶다면 DROP 후 `ADD`를 해야 합니다.
sql
-- 1. 기존 잘못된 노드 정보 삭제 (리더 FE에서 실행)
ALTER SYSTEM DROP FRONTEND "해당IP:9010";
-- 2. 다시 추가
ALTER SYSTEM ADD FOLLOWER "해당IP:9010";
3. FQDN과 IP 혼용 문제
만약 `fe.conf`에서 `enable_fqdn_mode = true`를 사용 중인데, 어떤 곳에서는 IP로 등록하고 어떤 곳에서는 Hostname으로 등록하려고 할 때 충돌이 발생할 수 있습니다.
* 체크리스트:
* SHOW FRONTENDS; 결과의 IP 컬럼과 본인이 추가하려는 주소가 일치하는지 확인하세요.
* `fe.conf`의 priority_networks 설정이 새 노드에서 올바르게 잡혀있는지 확인하세요. (엉뚱한 IP로 등록되려 할 수 있습니다.)
요약
1. `SHOW FRONTENDS;`로 현재 등록된 노드 목록을 확인한다.
2. 목록에 있다면 ADD 명령 없이 바로 `start_fe.sh --helper ...`를 실행한다.
3. 만약 설정을 완전히 새로 하고 싶다면 `ALTER SYSTEM DROP FRONTEND ...`로 먼저 지운 뒤 다시 ADD 한다.
References
• sql-reference/sql-statements/cluster-management/nodes_processes/ALTER_SYSTEM.md
• deployment/deploy_manually.md
References
• deployment/deploy_manually.md
• faq/Deploy_faq.md
• faq/operation_maintenance_faq.md
• deployment/upgrade.md
• administration/Meta_recovery.mdRonJay
09/21/2026, 5:20 AMRocky
09/21/2026, 5:20 AMbash
ps -ef | grep StarRocksFE
만약 프로세스가 검색된다면, 해당 프로세스가 이미 포트를 점유하고 있는 것입니다.
2. FE 프로세스 종료 (정상 종료 시도)
먼저 공식 스크립트를 사용하여 종료를 시도합니다.
bash
./bin/stop_fe.sh
만약 v3.3 이상의 버전에서 안전하게 종료하고 싶다면 -g 옵션을 사용할 수 있습니다.
bash
./bin/stop_fe.sh -g
3. 강제 종료 (정상 종료가 안 될 경우)
스크립트로 종료되지 않거나 프로세스가 응답하지 않는 경우, kill 명령어로 강제 종료합니다.
bash
# 위 1번에서 확인한 PID를 입력 (예: PID가 1234인 경우)
kill -9 1234
4. 남아있는 PID 파일 삭제
프로세스가 종료되었음에도 같은 에러가 발생한다면, 메타데이터 디렉토리에 fe.pid 파일이 남아있어 스크립트가 실행 중인 것으로 착각하는 것입니다.
* fe/conf/fe.conf 파일에서 meta_dir 경로를 확인합니다 (기본값은 fe/meta).
* 해당 경로 아래의 image 폴더 내에 있는 fe.pid 파일을 삭제합니다.
bash
# 예시 경로 (실제 meta_dir 경로에 따라 다를 수 있음)
rm /path/to/fe/meta/image/fe.pid
5. 다시 시작
프로세스와 PID 파일이 모두 정리되었다면 다시 시작합니다.
bash
./bin/start_fe.sh --daemon
주의: 한 서버에서 여러 개의 FE를 띄우려고 시도하는 중이라면, 각 FE마다 별도의 설치 경로와 다른 포트 설정을 가져야 합니다. 동일한 경로에서 두 번 실행할 수 없습니다.
References
• deployment/deploy_manually.md
• administration/management/graceful_exit.md
• faq/Deploy_faq.md
References
• administration/management/graceful_exit.md
• deployment/deploy_manually.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_FRONTENDS.mdRonJay
09/22/2026, 1:43 AMRocky
09/22/2026, 1:43 AMtrace times all select * ; 명령어가 동작하지 않는 이유는 크게 세 가지 가능성이 있습니다.
1. 문법 오류 (가장 유력)
StarRocks의 TRACE 구문은 다음과 같은 형식을 따릅니다.
sql
TRACE { TIMES | VALUES | LOGS | ALL } [ <module> ] <query_statement>
사용하신 `TRACE TIMES ALL ...`은 *두 가지 옵션(TIMES와 ALL)을 동시에 사용*했기 때문에 문법 오류가 발생합니다.
* TIMES: 각 단계별 *소요 시간*만 확인하고 싶을 때
* ALL: 시간(TIMES), 변수 값(VALUES), 로그(LOGS)를 모두 확인하고 싶을 때
또한, `ALL`을 모듈 이름으로 인식하려고 시도하지만, `ALL`은 유효한 모듈 이름(BASE, MV, OPTIMIZER, SCHEDULE, EXTERNAL)이 아닙니다.
올바른 예시:
_ 단순히 소요 시간을 보고 싶은 경우: TRACE TIMES SELECT _ FROM table;
_ 모든 디버그 정보를 보고 싶은 경우: TRACE ALL SELECT _ FROM table;
_ 특정 모듈(예: 옵티마이저)의 시간만 보고 싶은 경우: TRACE TIMES OPTIMIZER SELECT _ FROM table;
2. 버전 미지원
TRACE 명령어는 *StarRocks v3.2.0 버전부터 지원*됩니다. 사용 중인 StarRocks 버전이 이보다 낮다면 해당 명령어를 인식하지 못합니다.
* 버전 확인: SELECT aurora_version(); 또는 SHOW FRONTENDS;
3. 세미콜론 및 쿼리 완성도
`SELECT * ;`와 같이 대상 테이블이 없는 쿼리는 그 자체로 문법 오류입니다. TRACE 뒤에 오는 쿼리는 반드시 *실행 가능한 완전한 SQL 문장*이어야 합니다.
──────────
요약: 어떻게 써야 하나요?
보통 쿼리 플래닝 단계를 분석하려는 목적이라면 아래와 같이 사용해 보세요.
sql
-- 기본(BASE) 모듈의 시간 분석
TRACE TIMES SELECT * FROM your_table LIMIT 10;
-- 옵티마이저 단계만 상세 분석
TRACE TIMES OPTIMIZER SELECT * FROM your_table LIMIT 10;
만약 *실제 데이터 처리(BE 실행) 단계의 병목*을 찾으시는 것이라면 TRACE 대신 `EXPLAIN ANALYZE`를 권장합니다.
sql
EXPLAIN ANALYZE SELECT * FROM your_table LIMIT 10;
References
• developers/trace-tools/query_trace_profile.md
• knowledge/usage/best-practice.md
• best_practices/query_tuning/query_profile_text_based_analysis.md
References
• developers/trace-tools/query_trace_profile.md
• knowledge/usage/best-practice.md
• best_practices/query_tuning/query_profile_text_based_analysis.mdRonJay
09/22/2026, 2:07 AMRocky
09/22/2026, 2:08 AM_statistics_ 데이터베이스는 StarRocks의 CBO(Cost-Based Optimizer)가 사용하는 통계 정보를 저장하는 시스템 데이터베이스입니다. 이 중 external_column_statistics 테이블은 외부분석(Hive, Iceberg 등) 테이블의 통계 데이터가 담깁니다.
이 테이블의 *물리적인 디스크 사용량(용량)*을 확인하려면 아래의 커맨드를 사용하세요.
1. 테이블 단위 용량 확인 (가장 권장)
StarRocks에서 특정 데이터베이스 내 테이블들의 크기를 확인하는 표준 명령어입니다.
sql
SHOW DATA FROM _statistics_;
* 결과 확인: 출력 결과에서 `TableName`이 `external_column_statistics`인 행의 Size 컬럼을 확인하면 됩니다. (예: 1.2 GB, 500 MB 등)
2. 상세 파티션/태블릿별 용량 확인
만약 데이터가 너무 커서 상세 분석이 필요하다면 아래 명령어를 사용할 수 있습니다.
sql
SHOW PARTITIONS FROM _statistics_.external_column_statistics;
* 각 파티션별로 `DataSize`를 확인할 수 있습니다.
3. 참고: 데이터가 너무 크다면? (정리 방법)
만약 이 테이블의 용량이 너무 커서 정리가 필요하다면, StarRocks는 기본적으로 일정 기간이 지난 통계 데이터를 자동으로 삭제합니다. 관련 설정은 FE 설정 파일(fe.conf)에서 확인할 수 있습니다.
* `statistics_max_full_collect_data_size`: 전체 수집할 최대 데이터 크기 제한.
* `statistics_history_keep_secs`: 통계 히스토리 보관 주기 (기본값은 보통 24시간~수일).
주의: 시스템 테이블이므로 DELETE 구문을 직접 사용하여 데이터를 지우는 것은 권장되지 않으며, 필요한 경우 ANALYZE 명령을 통해 통계를 갱신하거나 보관 주기 설정을 조절하는 것이 좋습니다.
References
• using_starrocks/Cost_based_optimizer.md
• sql-reference/sql-statements/administration/SHOW_DATA.md
• administration/management/FE_configuration.md
References
• using_starrocks/Cost_based_optimizer.md
• sql-reference/information_schema/statistics.mdRonJay
09/22/2026, 2:10 AMRocky
09/22/2026, 2:11 AM_statistics_.external_column_statistics 테이블의 행 수가 약 35만 건인데 용량이 *1.3GB*라는 것은, 각 행이 상당히 큰 데이터(주로 Histogram 또는 HLL(HyperLogLog) 정보)를 포함하고 있음을 의미합니다. 보통 단순 수치형 통계만 있다면 이 정도 행 수에서 1GB를 넘지 않습니다.
이 상태에서 발생할 수 있는 주요 사이드 이펙트는 다음과 같습니다.
1. FE(Frontend) 메모리 부하 및 GC 발생
StarRocks의 옵티마이저는 쿼리 플래닝 시 통계 정보를 FE의 메모리(Statistic Cache)에 로드합니다.
* 메모리 점유: 1.3GB의 디스크 용량은 메모리에 로드될 때 역직렬화 과정을 거치며 수 배 더 커질 수 있습니다. FE의 Heap 메모리가 충분하지 않다면 *频繁한 Full GC*가 발생하여 클러스터 전체의 응답 속도가 느려지거나, 심할 경우 FE가 *OOM(Out of Memory)*으로 다운될 수 있습니다.
* 캐시 교체 overhead: 통계 캐시 크기 제한에 걸릴 경우, 빈번하게 캐시를 비우고 다시 로드하는 과정에서 CPU 사용량이 급증할 수 있습니다.
2. 쿼리 플래닝 시간 증가 (Planning Latency)
쿼리가 들어왔을 때 옵티마이저가 실행 계획을 세우는 시간이 길어집니다.
* 통계 로딩 지연: 외부 테이블을 조회하는 쿼리가 처음 실행될 때, 해당 테이블의 거대한 통계 데이터를 메모리로 읽어오는 과정에서 초기에 수 초 이상의 지연(Slow Query)이 발생할 수 있습니다.
* 계산 복잡도: 히스토그램 데이터가 너무 상세하면(Bucket이 많으면), 이를 계산하여 선택도(Selectivity)를 추정하는 과정 자체가 CPU를 많이 소모합니다.
3. Metadata 저장소(RocksDB/BDBJE) 부하
시스템 테이블의 데이터가 비대해지면 FE 내부의 메타데이터 관리 시스템에 부담을 줄 수 있습니다. 특히 체크포인트 생성이나 이미지 파일 쓰기 시 시간이 오래 걸릴 수 있습니다.
──────────
왜 이렇게 용량이 큰가요?
보통 다음과 같은 경우에 용량이 비대해집니다.
* Histogram 수집: ANALYZE 시 WITH HISTOGRAM 옵션을 사용하여 수집한 경우, 컬럼의 데이터 분포를 아주 상세하게 저장하므로 용량이 매우 커집니다.
* 고카디널리티 컬럼: 중복 값이 거의 없는 컬럼(ID, UUID 등)에 대해 HLL 통계를 수집하면 저장 데이터가 커집니다.
권장 조치 사항
1. 불필요한 통계 삭제: 사용하지 않는 외부 테이블의 통계가 있다면 `DROP ANALYZE`로 삭제하세요.
2. 수집 범위 제한: 모든 컬럼이 아닌, 조인(Join)이나 필터(Where) 조건에 자주 사용되는 핵심 컬럼에 대해서만 통계를 수집하도록 설정을 변경하세요.
3. FE 메모리 설정 확인: 현재 FE의 `JAVA_OPTS`에서 -Xmx 값이 충분한지 확인하십시오. 1.3GB의 통계 데이터가 있다면 최소 8GB~16GB 이상의 Heap 메모리를 권장합니다.
4. 자동 수집 설정 조절:
* statistics_max_full_collect_data_size 값을 조절하여 너무 큰 테이블은 샘플링 수집을 하도록 유도할 수 있습니다.
요약하자면, 현재 상태는 *FE 메모리 압박으로 인한 안정성 저하*가 가장 우려되는 상황입니다. 쿼리 실행 계획 수립 속도가 평소보다 느리다면 통계 데이터 최적화가 필요합니다.
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• sql-reference/sql-statements/administration/ANALYZE_TABLE.mdRonJay
09/22/2026, 4:48 AMRocky
09/22/2026, 4:49 AMSET GLOBAL 명령어도 기록되므로, 감사 로그(Audit Log)를 조회하면 범인을 찾을 수 있습니다.
* 방법 A: fe.audit.log 파일 확인
FE 서버의 로그 디렉토리(fe/log/fe.audit.log)에서 해당 변수명을 검색해 보세요.
bash
grep "변수명" fe.audit.log | grep "SET"
로그에는 *실행 시간, 실행한 유저, 접속 IP, 실행한 쿼리*가 모두 찍힙니다.
* 방법 B: AuditLoader 사용 시
만약 감사 로그를 테이블로 적재하고 있다면 아래와 같이 쿼리할 수 있습니다.
sql
SELECT timestamp, user, clientIp, stmt
FROM starrocks_audit_db*.starrocks_audit_tbl*
WHERE stmt LIKE '%SET GLOBAL 변수명%';
2. 누군가 잘못 설정했을 가능성 (주요 시나리오)
* ADMIN/OPERATE 권한자: `SET GLOBAL`은 SYSTEM-level OPERATE 권한이 있는 사용자만 가능합니다. 관리자 계정을 공유하거나 권한이 있는 다른 사용자가 실수로 덮어썼을 수 있습니다.
* 사용자별 속성 설정 (ALTER USER): 특정 유저에 대해 ALTER USER ... SET PROPERTIES ('session.변수명' = '값') 명령을 실행하면, 해당 유저는 글로벌 설정과 상관없이 고정된 값을 가지게 됩니다. 글로벌 변수가 바뀐 게 아니라 특정 유저의 값만 다르게 보인다면 이 경우일 수 있습니다.
3. 글로벌 vs 세션 혼동 (가장 흔한 케이스)
* 기존 세션 유지: `SET GLOBAL`은 *새로 맺어지는 커넥션*부터 적용됩니다. 이미 연결되어 있던 세션(예: DB 툴, 애플리케이션 커넥션 풀)은 예전 값을 계속 들고 있습니다.
* 만약 "바꿨는데 왜 예전 값이지?" 하고 누군가 다시 `SET`을 실행했다면 값이 꼬일 수 있습니다.
* 해결책: REFRESH CONNECTIONS; 명령어를 실행하면 기존 연결된 세션들에도 글로벌 변수가 강제 적용됩니다.
4. 시스템적 재설정 가능성 (드문 경우)
* FE 재시작: StarRocks의 글로벌 변수는 메타데이터에 저장되므로 재시작해도 유지되는 것이 정상입니다. 하지만 아주 드물게 버전 업그레이드 직후나 특정 버그로 인해 기본값으로 롤백되는 경우가 보고될 수 있습니다. (다만, 질문하신 것처럼 "하나만" 초기화됐다면 이 가능성은 매우 낮습니다.)
* 설정 파일(fe.conf)과의 충돌: 일부 변수는 fe.conf 파일에도 존재할 수 있습니다. 시스템이 재시작될 때 파일의 설정값이 우선적으로 로드되는 항목인지 확인이 필요합니다.
결론적으로 권장하는 조치
1. `fe.audit.log`를 먼저 뒤져보세요. 누가 언제 해당 변수를 건드렸는지 명확한 증거가 나옵니다.
2. 변수를 다시 설정한 후에는 `REFRESH CONNECTIONS;`를 실행하여 클러스터 전체 세션을 동기화하세요.
3. 특정 유저만 초기화된 것처럼 보인다면 `SHOW PROPERTY FOR '유저명';`을 통해 사용자별 커스텀 설정이 잡혀있는지 확인해 보세요.
References
• sql-reference/System_variable.md
• sql-reference/sql-statements/cluster-management/config_vars/REFRESH_CONNECTIONS.md
• administration/management/audit_loader.md
References
• sql-reference/System_variable.md
• faq/operation_maintenance_faq.md
• release_notes/release-2.5.mdRonJay
09/22/2026, 5:29 AMRocky
09/22/2026, 5:29 AMfree 명령어로 보면 메모리가 여전히 점유된 것으로 보이지만, 실제로는 새로운 쿼리가 들어오면 해당 메모리를 재사용합니다.
2. 쿼리 취소의 비동기성 (Zonbie Tasks)
쿼리를 `KILL QUERY`로 취소하더라도 모든 작업이 즉시 멈추지 않을 수 있습니다.
* 원인: 쿼리는 여러 CN/BE에 흩어져서 실행되는데, 취소 신호가 전달되고 각 실행 유닛(Fragment)이 리소스를 정리하는 데 시간이 걸립니다.
* 현상: 특히 네트워크 I/O가 대량으로 발생 중이거나 복잡한 Join 연산 중에는 취소 신호를 체크하는 로직까지 도달하는 데 지연이 발생하여, 쿼리 상태는 'Cancelled'지만 실제 프로세스는 메모리를 붙잡고 계속 도는 경우가 생깁니다.
3. 데이터 및 쿼리 결과 캐시 (Data Cache / Result Cache)
* Data Cache: 외부 테이블(Hive, Iceberg 등) 조회 시 CN의 디스크나 메모리에 데이터를 캐싱합니다. 이 메모리는 쿼리가 끝나도 다음 성능 향상을 위해 유지됩니다.
* Query Result Cache: 쿼리 결과를 메모리에 저장해 두는 기능이 켜져 있다면, 동일한 쿼리의 빠른 응답을 위해 메모리를 점유합니다.
4. 메타데이터 및 중간 결과 (Spill to Disk 관련)
* 중간 연산 결과가 너무 커서 디스크로 스필(Spill)되는 과정에서 취소될 경우, 관련 메모리 버퍼나 임시 파일 핸들이 완전히 정리되기 전까지 메모리를 점유할 수 있습니다.
──────────
상태를 확인하고 조치하는 방법
1. 현재 실제로 실행 중인 쿼리가 있는지 재확인
관리자 계정에서 아래 명령어로 실제 실행 중인 태스크가 남아있는지 확인합니다.
sql
-- 현재 실행 중인 쿼리 목록
SHOW PROCESSLIST;
-- 혹은 더 상세하게
SHOW PROC '/current_queries';
2. BE/CN의 상세 메모리 통계 확인
StarRocks가 인지하고 있는 메모리 사용처를 확인합니다. (이 결과에서 QueryContext 항목이 쿼리 종료 후에도 계속 크다면 문제가 있는 것입니다.)
sql
SHOW PROC '/mem_info';
3. 강제 메모리 반환 유도 (Jemalloc)
수동으로 Jemalloc에게 OS로 메모리를 반환하도록 명령할 수 있습니다. (테스트 용도)
bash
# CN/BE 노드 터미널에서 실행
curl -X POST http://<CN_IP>:<HTTP_PORT>/mem_release
4. 로그 확인
취소된 쿼리가 여전히 메모리를 잡고 있다면 cn.out 또는 `cn.warn.log`에서 `Fragment`가 종료되지 못하고 에러를 뱉고 있는지 확인해야 합니다.
요약
대부분은 1번(Jemalloc의 재사용 대기) 케이스이므로 `SHOW PROC '/mem_info'`를 통해 실제 쿼리가 메모리를 잡고 있는 것인지, 아니면 할당자가 들고 있는 것인지 구분하는 것이 우선입니다. 만약 시간이 지나도 mem_info 상의 특정 쿼리 ID가 메모리를 계속 점유한다면 프로세스 좀비화나 버그를 의심해 볼 수 있습니다.
References
• administration/management/memory_management/Memory_management.md
• sql-reference/sql-statements/administration/SHOW_PROC.md
• administration/management/memory_management/Memory_analysis_and_troubleshooting.md
References
• administration/management/memory_management/Memory_management.md
• administration/management/memory_management/Memory_analysis_and_troubleshooting.md
• using_starrocks/Query_result_cache.mdRonJay
09/22/2026, 8:44 AMRocky
09/22/2026, 8:45 AMsql
-- 'jdbc_catalog' 내의 'sales_db'를 조회하는 모든 쿼리를 rg1에 할당
CREATE RESOURCE GROUP rg1
TO (db='sales_db') -- JDBC Catalog 내부의 DB명을 지정
WITH ("concurrency_limit" = "5", "cpu_weight" = "10");
(참고: 분류기의 db 조건은 쿼리가 참조하는 데이터베이스 명을 기준으로 작동합니다.)
* 방법 B: 전용 유저 기반 분류기
외부 데이터 소스(JDBC) 전용 유저를 생성하고, 해당 유저가 실행하는 모든 쿼리를 리소스 그룹에 할당합니다.
sql
CREATE RESOURCE GROUP rg_jdbc
TO (user='jdbc_user')
WITH ("concurrency_limit" = "10");
* 방법 C: 세션 변수 수동 지정
쿼리를 실행하기 전 세션 수준에서 직접 리소스 그룹을 지정합니다.
sql
SET resource_group = 'rg_jdbc';
SELECT * FROM jdbc_catalog.db.table;
2. JDBC Catalog 동시 쿼리 제한 방법
JDBC Catalog를 통해 나가는 쿼리 부하를 조절하는 방법은 크게 두 가지 층위가 있습니다.
① 리소스 그룹의 concurrency_limit (소프트웨어적 제한)
위에서 만든 리소스 그룹에 `concurrency_limit`을 설정하면, 해당 그룹에 할당된 JDBC 조회 쿼리의 동시 실행 수를 제한할 수 있습니다.
* 작동 방식: 설정된 제한치를 넘으면 쿼리가 대기열(Queue)에 쌓이거나 실패합니다.
* 버전 참고: v3.1.4 이상부터는 FE에서 전역적으로 동시성을 관리하므로 더 정확한 제한이 가능합니다.
② FE의 JDBC 커넥션 풀 설정 (물리적 제한)
StarRocks FE 설정 항목 중에 JDBC 소스로 맺을 수 있는 최대 물리 커넥션 수를 제한하는 옵션이 있습니다.
* jdbc_connection_pool_size: JDBC Catalog에 접근하기 위한 JDBC 커넥션 풀의 최대 크기입니다. (기본값: 8)
* 이 설정은 모든 유저와 모든 JDBC Catalog 쿼리에 대해 전역적으로 적용되는 물리적 통로의 개수 제한입니다.
요약
* 특정 JDBC Catalog에만 제한을 걸고 싶다면: 전용 유저를 만들거나 DB 분류기를 사용하여 *Resource Group*을 생성하고 `concurrency_limit`을 설정하세요.
* 소스 DB(원본)의 부하를 원천 차단하고 싶다면: FE 설정의 `jdbc_connection_pool_size`를 조정하세요.
References
• administration/management/resource_management/resource_group.md
• administration/management/resource_management/query_queues.md
• administration/management/FE_configuration.md
References
• faq/resource_isolation_faq.md
• administration/management/FE_configuration.md
• administration/management/resource_management/resource_group.mdRonJay
09/28/2026, 8:07 AMRocky
09/28/2026, 8:08 AMenable_statistic_collect
* 동작 방식: 자동 통계 수집 기능의 *전체 메인 스위치*입니다. `TRUE`일 때만 시스템이 주기적으로 데이터 변경량을 확인하여 통계 수집 태스크를 스케줄링합니다.
* 비활성화 시 효과: 모든 자동/사용자 정의 자동 수집 태스크가 중단됩니다. 통계 정보가 자동으로 업데이트되지 않으므로, 데이터가 계속 변하는데 수동으로 `ANALYZE`를 해주지 않으면 *시간이 갈수록 최적화되지 않은 비효율적인 실행 계획이 생성*될 가능성이 매우 높아집니다.
2. enable_collect_full_statistic
* 동작 방식: 자동 수집 시 '전체 통계(Full Statistics)' 수집을 허용할지 결정합니다. `TRUE`이면 조건에 맞는 테이블에 대해 전체 데이터를 스캔하여 정확한 통계를 뽑습니다.
* 비활성화 시 효과: 자동 수집 방식이 전체 스캔에서 샘플링(Sampled) 수집 방식으로 변경됩니다.
* 장점: 통계 수집 과정에서 발생하는 시스템 리소스(CPU/IO) 부하를 크게 줄일 수 있습니다.
* 단점: 데이터 분포가 불균일할 경우 샘플링 데이터만으로는 정확한 통계를 얻지 못해 쿼리 성능이 저하될 수 있습니다.
3. enable_predicate_columns_collection
* 동작 방식: 쿼리에서 실제 조건절(WHERE, JOIN, GROUP BY)에 사용된 컬럼(Predicate Columns)이 무엇인지 기록하고, 해당 컬럼 위주로 통계를 수집하도록 하는 최적화 기능입니다.
* 비활성화 시 효과: 어떤 컬럼이 자주 쓰이는지 기록하지 않습니다.
* 이로 인해 statistic_auto_collect_predicate_columns_threshold 설정과 연계된 "필요한 컬럼만 선별해서 통계를 수집"하는 지능형 동작이 수행되지 않으며, 테이블의 모든 컬럼 혹은 불필요한 컬럼까지 통계를 뽑게 되어 리소스 낭비가 발생할 수 있습니다.
4. enable_statistic_collect_on_first_load
* 동작 방식: 테이블이나 파티션에 *처음으로 데이터가 로드*될 때(첫 INSERT 등) 즉시 통계를 수집합니다.
* 비활성화 시 효과: 데이터가 처음 들어왔을 때 통계가 없는 상태가 유지됩니다.
* 새로 생성된 테이블에 대량의 데이터를 넣고 바로 쿼리를 날릴 경우, 통계 정보가 전혀 없어서(0건으로 인식 등) 매우 느린 실행 계획이 선택될 수 있습니다.
5. enable_statistic_collect_on_update
* 동작 방식: UPDATE 문에 의해 데이터가 변경되었을 때 통계 업데이트를 트리거합니다. (v3.5.11+ / v4.0.4+ 도입)
* 비활성화 시 효과: `UPDATE`로 인한 데이터 변경사항이 통계에 즉시 반영되지 않습니다. `UPDATE`가 빈번한 업무 환경에서 통계 정보가 실제 데이터와 동떨어지는 원인이 됩니다.
──────────
요약 및 종합 영향
현재 질문자님은 enable_query_trigger_analyze = false 상태입니다. 이 설정은 "쿼리 실행 시 통계가 없으면 즉석에서 수집"하는 기능을 끈 것입니다.
이 상황에서 위 5가지 설정까지 모두 혹은 일부 비활성화한다면:
1. 리소스 보호: 통계 수집을 위한 백그라운드 부하(CPU/Memory/IO)는 거의 완벽하게 차단할 수 있습니다.
2. 성능 위험: "자동 수집도 안 되고 + 쿼리 시점에 수집도 안 되는" 상태가 됩니다.
* 기존 테이블의 데이터 분포가 크게 변하거나 신규 테이블이 추가될 때, Optimizer는 *오래된 통계나 기본값*을 사용하게 됩니다.
* 이는 잘못된 Join 순서 결정, 잘못된 인덱스 선택 등으로 이어져 *서비스 중 장애 수준의 쿼리 지연*을 초래할 수 있습니다.
권장 사항: 시스템 부하 때문이라면 모든 기능을 끄기보다는 `enable_collect_full_statistic`만 `false`로 바꾸어 샘플링 방식으로 유도하거나, `statistic_auto_analyze_start_time`을 조정해 야간에만 동작하도록 설정하는 방식을 추천드립니다.
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• sql-reference/sql-statements/administration/ANALYZE_TABLE.md
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• release_notes/release-3.2.md
References
• administration/management/FE_configuration.md
• using_starrocks/Cost_based_optimizer.mdRonJay
09/28/2026, 8:45 AMRocky
09/28/2026, 8:45 AMSELECT 쿼리만 수행함에도 불구하고 PUBLISH 버전이 계속 생성되는 이유는 StarRocks 내부에서 *데이터를 변경하는 비동기 작업들이 백그라운드에서 계속 실행*되고 있기 때문입니다.
shared_data 모드(Cloud-native)에서 `PUBLISH`는 데이터가 스토리지에 완전히 쓰여지고 가시성(Visibility)이 확보되었음을 의미하며, 주로 다음과 같은 원인으로 발생합니다.
1. 자동 통계 수집 (가장 유력한 원인)
이전 질문에서 확인하신 통계 수집 기능(enable_statistic_collect) 때문입니다.
* 동작: 사용자가 SELECT 쿼리를 날리면 Optimizer는 통계 정보를 조회합니다. 이때 통계가 오래되었거나 없으면 StarRocks는 내부 시스템 테이블(_statistics_.column_statistics 등)에 통계 정보를 계산해서 INSERT 합니다.
* 결과: 시스템 테이블에 데이터를 쓰는 것도 하나의 트랜잭션이므로 PUBLISH 단계가 발생합니다.
2. 백그라운드 컴팩션 (Compaction)
shared_data 모드에서도 데이터 효율을 위해 작은 파일들을 합치는 컴팩션이 발생합니다.
* 동작: 비록 사용자가 새 데이터를 넣지 않더라도, 기존에 업로드된 조각 파일(Segment)들을 백그라운드에서 더 큰 파일로 병합합니다.
* 결과: 컴팩션이 완료되면 새로운 메타데이터 버전을 확정 지어야 하므로 PUBLISH 트랜잭션이 수행됩니다.
3. 비동기 구체화 뷰 (Asynchronous Materialized View)
만약 시스템에 *Async MV*가 정의되어 있다면, 원본 테이블의 데이터가 변하지 않았더라도 설정된 주기에 따라 새로 고침(Refresh)을 시도할 수 있습니다.
* 이 과정에서 MV 테이블에 새로운 결과가 쓰여지며 `PUBLISH`가 발생합니다.
4. 캐시 메타데이터 업데이트
shared_data 모드는 객체 스토리지(S3 등)의 데이터를 로컬(CN/BE)에 캐싱합니다.
* 쿼리 실행 시 캐시 상태가 변하거나, 메타데이터 업데이트가 필요할 경우 내부적인 상태 관리를 위해 아주 미세한 쓰기 작업이 수반될 수 있습니다.
──────────
확인 방법
실제로 어떤 작업이 `PUBLISH`를 일으키는지 확인하려면 다음 명령어를 사용해 보시기 바랍니다.
1. 현재 진행 중이거나 최근 종료된 트랜잭션 확인:
sql
-- 어떤 테이블에서 트랜잭션이 발생하는지 확인 가능
SHOW PROC '/transactions';
* 여기서 `Label`이나 `TableNames`를 보시면 어떤 내부 작업(예: analyze_... 또는 컴팩션 관련 이름)이 돌고 있는지 알 수 있습니다.
2. 통계 수집 태스크 확인:
sql
-- 현재 돌아가고 있는 통계 수집 작업 확인
SHOW ANALYZE STATUS;
해결 방안
만약 SELECT 성능에 영향을 줄 정도로 PUBLISH 부하가 심하다면:
* 앞서 문의하신 *통계 자동 수집 관련 설정들을 비활성화*하거나 수집 주기를 늦추십시오.
* 컴팩션이 너무 자주 일어난다면 관련 설정을 튜닝해야 할 수도 있지만, 이는 시스템 안정성을 위해 가급적 기본값을 유지하는 것이 좋습니다.
요약하자면: `SELECT`만 수행하더라도 *Optimizer를 위한 통계 정보 갱신(쓰기)*과 스토리지 최적화를 위한 컴팩션 때문에 PUBLISH 로그는 정상적으로 발생할 수 있습니다.
References
• administration/management/memory_management/Memory_analysis_and_troubleshooting.md
• sql-reference/sql-statements/administration/SHOW_PROC.md
• using_starrocks/Cost_based_optimizer.md
• administration/management/resource_management/resource_group.md
References
• using_starrocks/Cost_based_optimizer.md
• sql-reference/sql-statements/administration/SHOW_PROC.md
• administration/management/resource_management/resource_group.md
• administration/management/memory_management/Memory_analysis_and_troubleshooting.md
• table_design/compaction.md
/compaction)RonJay
09/28/2026, 8:51 AMRocky
09/28/2026, 8:51 AM_statistics_)*에 저장합니다.
* 통계 수집 시: 내부 테이블에 `INSERT`가 발생하므로 `PUBLISH`가 일어납니다.
* 통계 테이블 컴팩션: 이 시스템 테이블도 Internal Catalog에 속하는 OLAP 테이블입니다. 통계 데이터가 자주 업데이트되면 작은 파일들이 생기고, 이를 합치기 위해 *백그라운드 컴팩션*이 돌아가며 또 다른 `PUBLISH`를 발생시킵니다.
2. 이전에 로드했던 내부 테이블의 정리 작업
만약 과거에 테스트 용도로라도 Internal Catalog에 데이터를 넣은 적이 있다면, 데이터 로드가 멈춘 이후에도 시스템은 최적의 상태를 만들기 위해 뒤늦게 컴팩션 작업을 완료하고 버전을 업데이트(Publish)할 수 있습니다.
──────────
무엇이 돌고 있는지 확인하는 방법
어떤 테이블에서 `PUBLISH`를 일으키는 작업이 도는지 아래 명령어로 직접 확인해 보시기 바랍니다.
1. 현재 진행 중인 컴팩션 확인
sql
-- 어떤 데이터베이스/테이블에서 컴팩션이 도는지 리스트가 나옵니다.
SHOW PROC '/compactions';
* 여기서 Partition 열을 보시면 _statistics_ 관련 테이블인지, 아니면 다른 내부 테이블인지 알 수 있습니다.
2. 최근 발생한 트랜잭션 내역 확인
sql
-- 최근에 완료되거나 진행 중인 트랜잭션의 레이블과 테이블 명을 확인합니다.
SHOW PROC '/transactions';
* `Label`에 `analyze_`라는 단어가 포함되어 있다면 통계 수집 때문입니다.
* `Label`에 `compaction_`이라는 단어가 포함되어 있다면 컴팩션 때문입니다.
요약
* 컴팩션 대상: 오직 Internal Catalog (시스템 테이블 포함)입니다.
* JDBC Catalog만 쓰는데 왜 발생하나? JDBC 테이블의 성능을 위해 StarRocks가 내부적으로 관리하는 *'통계 정보 테이블'*이 Internal Catalog에 저장되어 있고, 이 테이블에 대한 쓰기/병합 작업이 발생하기 때문일 가능성이 큽니다.
만약 이 작업들이 시스템에 부하를 준다면, 앞서 설명해 드린 대로 enable_statistic_collect = false 설정을 통해 통계 자동 수집을 끄면 관련 PUBLISH 발생 빈도를 크게 줄일 수 있습니다.
References
• table_design/compaction.md
• administration/management/compaction.md
• using_starrocks/Cost_based_optimizer.md
• faq/shared_data_faq.md
• knowledge/admin_and_operation/shared_data_compaction.md
• sql-reference/sql-statements/administration/SHOW_PROC.md
• administration/management/FE_configuration.md
• deployment/shared_data/feature-support-shared-data.md
• knowledge/usage/load/shared_data_batch_ingestion.md
References
• administration/management/compaction.md
• knowledge/admin_and_operation/shared_data_compaction.mdRonJay
09/28/2026, 8:55 AMRocky
09/28/2026, 8:56 AM_statistics_ 데이터베이스 내의 5개 테이블은 StarRocks의 *관측성(Observability)*과 *쿼리 최적화(CBO)*를 위해 내부적으로 관리되는 테이블들입니다. shared_data 모드에서 이 테이블들에 데이터가 쌓이면 이를 병합하기 위해 백그라운드 컴팩션이 돌고, 그 과정에서 `PUBLISH`가 발생하게 됩니다.
각 테이블의 역할과 트리거 시점, 비활성화 방법은 다음과 같습니다.
1. task_run_history
* 역할: `ANALYZE`(통계 수집) 작업이나 `SUBMIT TASK`로 생성된 모든 *태스크의 실행 이력*을 저장합니다. information_schema.task_runs 뷰의 원본 데이터를 담고 있습니다.
* 트리거: 자동/수동 통계 수집 작업이 완료될 때마다 이력이 한 줄씩 추가됩니다.
* 비활성화: 통계 관련 태스크라면 `enable_statistic_collect = false`로 중지할 수 있습니다. 이미 쌓인 이력은 관리자가 수동으로 DELETE 문을 사용하여 삭제할 수 있습니다.
2. loads_history
* 역할: StarRocks에서 수행된 *모든 데이터 로드 작업*(Broker Load, Stream Load, INSERT INTO 등)의 상세 기록을 보관합니다.
* 트리거: 데이터 로드가 완료되면 메모리에 있던 로드 정보가 이 테이블로 영구 저장(Persistence)됩니다.
* 비활성화: 완전히 끄는 설정은 없으나, 로드가 없다면 데이터가 쌓이지 않습니다. 만약 `SELECT`만 하는데 이 테이블에 작업이 있다면, 다른 유저나 시스템이 백그라운드에서 데이터를 로드하고 있는지 확인해야 합니다. (`SHOW LOAD`로 확인 가능)
3. predicate_columns
* 역할: 쿼리의 WHERE, JOIN, GROUP BY 절에서 *필터로 사용된 컬럼이 무엇인지*를 기록합니다. Optimizer는 이 정보를 보고 "자주 쓰이는 컬럼" 위주로 통계를 수집하도록 최적화합니다.
* 트리거: 사용자가 SELECT 쿼리를 실행할 때, 새로운 조건절 컬럼이 발견되면 기록됩니다.
* 비활성화: `FE.conf`에서 *`enable_predicate_columns_collection = false`*로 설정하면 수집을 중단합니다.
4. column_statistics
* 역할: 내부 카탈로그(Internal Catalog) 테이블들의 실제 통계 데이터(NDV, Min, Max, Null Count 등)를 저장합니다.
* 트리거: 자동 혹은 수동으로 `ANALYZE`를 수행할 때 데이터가 갱신됩니다.
* 비활성화: enable_statistic_collect = false 설정 시 자동 수집 및 기록이 중단됩니다.
5. external_column_statistics
* 역할: Hive, Iceberg, JDBC 등 외부 카탈로그(External Catalog) 테이블의 통계 데이터를 저장합니다.
* 트리거: 외부 테이블에 대해 ANALYZE 작업이 수행될 때 기록됩니다.
* 비활성화: `column_statistics`와 마찬가지로 *`enable_statistic_collect = false`*로 제어합니다.
──────────
요약 및 조치 방안
사용자께서는 `SELECT`만 사용 중임에도 이 테이블들에서 컴팩션이 발생하는 이유는 다음과 같습니다:
1. Predicate 수집: 쿼리를 날릴 때마다 `predicate_columns`에 "어떤 컬럼을 썼는지" 기록하고 있기 때문입니다.
2. 통계 자동 수집: `enable_statistic_collect`가 `true`라면, 시스템이 주기적으로 통계를 계산해서 `column_statistics`나 `external_column_statistics`에 쓰기 때문입니다.
3. 이력 관리: 위 작업들이 수행된 결과가 `task_run_history`에 계속 쌓이기 때문입니다.
컴팩션과 `PUBLISH`를 최소화하려면:
* 이미 진행하신 enable_query_trigger_analyze = false 외에도,
* enable_statistic_collect = false (자동 통계 수집 중단)
* enable_predicate_columns_collection = false (조건절 컬럼 기록 중단)
를 설정하시면 SELECT 시 발생하는 대부분의 내부 쓰기 작업을 막을 수 있습니다.
주의: 이 설정을 끄면 데이터 변화에 따른 통계 자동 업데이트가 멈추므로, 실행 계획이 부정확해질 수 있습니다. 데이터 변화가 큰 시점에 수동으로 `ANALYZE`를 한 번씩 돌려주시는 것이 좋습니다.
References
• using_starrocks/Cost_based_optimizer.md
• loading/loading_introduction/troubleshooting_loading.md
• sql-reference/information_schema/loads.md
• administration/management/FE_configuration.md
• sql-reference/sql-statements/loading_unloading/ETL/SUBMIT_TASK.md
References
• loading/loading_introduction/troubleshooting_loading.md
• sql-reference/information_schema/loads.md
• sql-reference/information_schema/statistics.md
• sql-reference/information_schema/routine_load_jobs.mdRonJay
09/29/2026, 8:48 AMRocky
09/29/2026, 8:48 AMsql
-- 설정이 ON으로 되어 있는지 확인
ADMIN SHOW AUTOMATED CLUSTER SNAPSHOT;
-- 또는 설정 변수 확인
SHOW VARIABLES LIKE '%automated_cluster_snapshot%';
2. 스냅샷 작업 상태 조회 (핵심)
StarRocks는 스냅샷 작업의 진행 상황과 에러 메시지를 시스템 뷰에 기록합니다. 가장 먼저 아래 쿼리를 실행하여 에러 내용을 확인하십시오.
sql
SELECT * FROM information_schema.cluster_snapshot_jobs
ORDER BY created_time DESC;
* state 컬럼: ERROR 상태인 작업이 있는지 확인합니다.
* error_message 컬럼: 실패 원인이 구체적으로 명시되어 있습니다 (예: 권한 부족, 스토리지 볼륨 연결 실패 등).
3. 트리거 조건 확인 (Checkpoint)
자동 스냅샷은 단순히 시간만 흐른다고 생성되는 것이 아니라, *FE의 메타데이터 체크포인트(Image 생성)가 완료된 직후*에 트리거됩니다.
* 체크포인트 발생 확인: `fe/log/fe.log`에서 checkpoint 혹은 image 관련 로그를 검색하여 최근에 메타데이터 이미지 파일이 정상적으로 생성되었는지 확인하십시오.
* 간격 설정: automated_cluster_snapshot_interval_seconds (기본값 600초) 설정값이 너무 길게 잡혀 있지 않은지 확인하십시오.
4. 스토리지 볼륨(Storage Volume) 확인
스냅샷은 객체 스토리지에 저장됩니다.
* 권한 문제: 스냅샷 전용 Storage Volume을 지정했다면, 해당 경로에 대해 FE가 *쓰기 권한*을 가지고 있는지 확인해야 합니다.
* 기본 볼륨 확인: 별도의 볼륨을 지정하지 않았다면 클러스터의 `Default Storage Volume`을 사용합니다. 이 볼륨의 상태가 `NORMAL`인지 확인하십시오.
sql
SHOW STORAGE VOLUMES;
5. FE 로그 디버깅
위의 뷰에서 정보를 얻지 못했다면 FE Leader 노드의 로그(fe.log)를 직접 분석해야 합니다.
* 키워드: ClusterSnapshot, automated_cluster_snapshot, SnapshotManager
* 체크포인트 로그: `finished save image`라는 문구 이후에 스냅샷 작업이 시작되는지 확인하십시오.
요약 가이드
1. `information_schema.cluster_snapshot_jobs`에서 *`error_message`*를 먼저 본다.
2. *v3.4.2 이상*이며 Shared-data 모드인지 확인한다.
3. *Storage Volume*에 쓰기 권한이 있는지, 용량이 충분한지 확인한다.
4. 로그에서 *Checkpoint(Image)*가 정상적으로 수행되고 있는지 확인한다.
만약 `cluster_snapshot_jobs`에 이력 자체가 남지 않는다면, FE Leader 노드에서 스냅샷 스케줄러가 정상적으로 시작되지 않은 것일 수 있으므로 FE 재시작을 고려하거나 `fe.warn.log`를 정밀 점검해야 합니다.
References
• administration/cluster_snapshot.md
• faq/shared_data_faq.md
• sql-reference/sql-statements/cluster-management/storage_volume/CREATE_STORAGE_VOLUME.md
References
• administration/cluster_snapshot.md
• faq/shared_data_faq.md
References
• administration/cluster_snapshot.md
• faq/shared_data_faq.mdRonJay
09/29/2026, 8:53 AMRocky
09/29/2026, 8:54 AMsql
-- Leader FE에서 메타데이터 이미지(Checkpoint) 생성을 강제로 시작합니다.
ALTER SYSTEM CREATE IMAGE;
* 이 작업은 비동기로 진행됩니다.
* `fe.log`에서 triggering a new checkpoint manually... 로그로 시작을 확인할 수 있고, finished save image... 로그가 나오면 스냅샷 생성이 완료됩니다.
* 생성된 스냅샷은 automated_cluster_snapshot_{timestamp} 형식의 이름을 가집니다.
2. 전용 수동 생성 명령어 (v3.5 이상 권장)
StarRocks 최신 버전(v3.5 이상)에서는 자동 스냅샷 외에도 사용자가 이름을 지정하여 수동으로 스냅샷을 생성하는 기능이 추가되었습니다. (시스템 뷰의 manual 타입이 이에 해당합니다.)
sql
-- 수동으로 특정 이름을 가진 클러스터 스냅샷 생성
CREATE CLUSTER SNAPSHOT <snapshot_name>
[STORAGE VOLUME <storage_volume_name>];
* snapshot_name: 사용자가 식별할 수 있는 이름을 지정합니다.
* STORAGE VOLUME: (선택 사항) 기본 볼륨 외에 특정 스토리지 볼륨에 저장하고 싶을 때 지정합니다.
3. 진행 상황 확인
수동으로 명령어를 실행한 후, 제대로 작업이 돌고 있는지 아래 쿼리로 모니터링하십시오.
sql
-- 현재 진행 중인 스냅샷 작업의 상태(SNAPSHOTING, FINISHED, ERROR 등) 확인
SELECT * FROM information_schema.cluster_snapshot_jobs
ORDER BY created_time DESC;
-- 생성 완료된 스냅샷 목록 및 경로 확인
SELECT * FROM information_schema.cluster_snapshots;
주의사항
* Shared-data 전용: 이 기능은 Shared-nothing(전통적인 BE 방식) 클러스터에서는 지원되지 않습니다.
* 저장 공간: 수동 스냅샷은 자동 스냅샷과 달리 자동으로 삭제(Purge)되지 않고 계속 유지될 수 있으므로, 생성 후 스토리지 용량 관리에 유의해야 합니다.
* Beta 기능: v3.4.x 대에서는 아직 Beta 단계이므로, 실제 운영 환경에 적용하기 전 반드시 테스트를 거치시기 바랍니다.
References
• administration/cluster_snapshot.md
• sql-reference/sql-statements/cluster-management/nodes_processes/ALTER_SYSTEM.md
• sql-reference/sql-statements/cluster-management/storage_volume/CREATE_STORAGE_VOLUME.md
References
• administration/cluster_snapshot.md
• sql-reference/sql-statements/cluster-management/nodes_processes/ALTER_SYSTEM.mdRonJay
09/30/2026, 5:21 AMRocky
09/30/2026, 5:21 AM_statistics_.external_column_statistics 테이블에 저장된 수집된 통계.
2. 외부 메타데이터: Iceberg Manifest/Puffin 파일에서 읽어온 통계 (`enable_get_stats_from_external_metadata = true`인 경우).
만약 과거에 ANALYZE 명령을 통해 통계를 한 번이라도 수집했다면, `enable_query_trigger_analyze = false`로 설정했더라도 이미 저장된 *내부 통계 정보가 외부 메타데이터보다 우선적으로 사용*됩니다. 이 경우 세션 변수를 바꿔도 옵티마이저는 이미 가지고 있는 내부 데이터를 쓰기 때문에 실행 계획에 변화가 없습니다.
② Iceberg 메타데이터에 NDV(Cardinality) 정보 부재
`enable_iceberg_column_statistics`를 `true`로 켜면 StarRocks는 Iceberg의 *Puffin 파일*을 찾아 NDV(Distinct Value 개수)를 읽으려 시도합니다.
* 하지만 많은 Iceberg 테이블이 생성될 때 Puffin 파일(NDV 정보 포함) 없이 생성됩니다.
* Puffin 파일이 없다면 옵티마이저는 여전히 NDV 값을 알 수 없으므로, 변수를 켜기 전과 후의 실행 계획(Join Reorder 등)이 동일하게 유지되어 성능 차이가 나지 않습니다.
③ 행 수(Row Count) 정보만으로 충분한 경우
enable_get_stats_from_external_metadata = true 설정이 되어 있다면, StarRocks는 기본적으로 테이블의 전체 행 수(Row Count)를 가져옵니다.
* 쿼리 10종의 실행 계획이 이미 전체 행 수 정보만으로 최적의 Join 순서나 Join Type(Broadcast vs Shuffle)을 결정한 상태라면, 상세 컬럼 통계(Min/Max/Null)가 추가되어도 실행 계획이 바뀌지 않아 성능이 동일할 수 있습니다.
──────────
2. 성능 차이가 없는 이유를 확인하는 방법 (디버깅)
변수 설정에 따른 실제 효과를 눈으로 확인하려면 다음 세 단계를 순서대로 수행하십시오.
STEP 1. 실행 계획의 비용(Cost) 비교
가장 확실한 방법은 EXPLAIN COSTS 명령어로 옵티마이저가 계산한 통계 수치를 비교하는 것입니다.
sql
-- 옵션 OFF 상태에서 실행
EXPLAIN COSTS SELECT ... ;
-- 옵션 ON 상태에서 실행
EXPLAIN COSTS SELECT ... ;
* 확인 포인트: 각 연산자(Scan, Join)의 cardinality, column stats 항목을 확인하십시오. 만약 두 경우의 `ndv`나 range 값이 동일하다면, 옵티마이저가 외부 메타데이터에서 새로운 정보를 얻지 못한 것입니다.
STEP 2. 실제 사용된 통계 출처 확인 (Query Profile)
쿼리 실행 후 SET enable_profile = true; 상태에서 프로필을 확인합니다.
* 확인 포인트: 프로필 내 Query Planning 섹션에서 통계를 가져온 소스가 `External`인지, 아니면 내부 캐시된 `Statistics`인지 확인 가능합니다. (일부 버전에서는 `EXPLAIN VERBOSE`에서도 확인 가능)
STEP 3. 내부 저장 통계 유무 확인
StarRocks가 이미 통계를 가지고 있어서 외부 메타데이터를 무시하는지 확인합니다.
sql
SELECT * FROM _statistics_.external_column_statistics
WHERE table_name = 'your_iceberg_table_name';
* 데이터가 조회된다면, DELETE 문으로 해당 통계를 삭제한 뒤 변수 조절에 따른 성능 차이를 다시 테스트해 보아야 합니다.
STEP 4. Iceberg 메타데이터 파일 확인
Iceberg 테이블에 실제로 상세 통계가 있는지 확인합니다.
sql
-- Iceberg 메타데이터 테이블 조회 (v3.4.1+)
SELECT * FROM your_catalog.your_db.your_table$files;
* column_sizes, value_counts, nan_value_counts 등의 컬럼이 채워져 있는지, 특히 NDV 정보를 담은 Puffin 파일 관련 설정이 Iceberg 테이블에 되어 있는지 확인하십시오.
요약
두 변수의 차이가 없는 것은 *(1) 이미 StarRocks 내부에 통계가 있거나 (2) Iceberg 데이터 자체에 NDV 정보가 없거나 (3) 현재 실행 계획이 이미 최적*이기 때문일 가능성이 매우 높습니다. `EXPLAIN COSTS`를 통해 ndv 수치가 변하는지 확인하는 것이 가장 빠른 확인 방법입니다.
References
• data_source/catalog/iceberg/iceberg_catalog.md
• using_starrocks/Cost_based_optimizer.md
• sql-reference/System_variable.md
• data_source/feature-support-data-lake-analytics.md
References
• administration/management/FE_configuration.md
• using_starrocks/Cost_based_optimizer.md
• data_source/catalog/iceberg/iceberg_catalog.mdRonJay
09/30/2026, 5:22 AMRocky
09/30/2026, 5:23 AMenable_get_stats_from_external_metadata = true 설정이 되어 있으면, StarRocks는 Iceberg Manifest 파일에서 *테이블의 전체 행 수(Row Count)*를 가져옵니다.
* 대부분의 CBO(Cost-Based Optimizer) 결정(예: Join 순서 결정, Broadcast vs Shuffle Join 선택)은 컬럼의 상세 분포보다 *데이터의 양(행 수)*에 훨씬 더 큰 영향을 받습니다.
* 만약 행 수 정보만으로 이미 최적의 실행 계획이 도출되었다면, 컬럼 통계(Min/Max/NDV)를 추가로 읽어오더라도 실행 계획이 바뀌지 않으므로 성능 차이가 발생하지 않습니다.
② NDV(Cardinality) 정보를 위한 Puffin 파일의 부재
* `enable_iceberg_column_statistics`를 활성화하면 StarRocks는 Iceberg의 *Puffin 파일*에서 NDV(고유값 개수) 정보를 읽으려 시도합니다.
* 하지만 많은 Iceberg 테이블들이 생성될 때 상세 통계(Puffin) 없이 생성됩니다. 만약 Puffin 파일이 없다면 옵티마이저는 여전히 NDV 값을 알 수 없으므로, 변수 설정 전후의 실행 계획이 동일하게 유지됩니다.
③ 상세 컬럼 통계의 활용도가 낮은 쿼리 패턴
* 테스트하신 10종의 쿼리가 단순 조회이거나, 조인 조건이 명확하거나, 필터링 효율이 이미 행 수 정보만으로도 충분히 계산되는 경우라면 상세 통계의 영향력이 미미합니다.
──────────
2. 원인 파악을 위한 디버깅 방법
성능 차이가 없는 이유가 "통계를 못 읽어서"인지 "읽었지만 계획이 같아서"인지 확인하려면 다음 방법을 순서대로 실행해 보십시오.
방법 A: EXPLAIN COSTS 비교 (가장 권장)
두 옵션의 ON/OFF 상태에서 각각 실행 계획의 비용(Cost) 정보를 비교합니다.
sql
-- 옵션 OFF/ON 각각 수행 후 결과 비교
EXPLAIN COSTS <당신의_쿼리>;
* 확인 포인트: 각 연산자(Iceberg Scan 등) 하단의 `cardinality`와 column statistics 항목을 보십시오.
* 만약 두 경우 모두 ndv 값이 동일하거나, ndv 정보가 아예 표시되지 않는다면 StarRocks가 외부 통계를 제대로 가져오지 못한 것입니다.
* 만약 ndv 값은 바뀌었지만 전체 실행 계획(Join 구조 등)이 동일하다면, 상세 통계가 실행 계획을 바꿀 만큼의 임계치를 넘지 못한 것입니다.
방법 B: enable_metadata_profile 활용 (v3.3.3+)
메타데이터를 가져오는 과정 자체에 대한 프로필을 확인합니다.
sql
SET enable_metadata_profile = true;
-- 쿼리 실행 후
SHOW PROFILE;
* 확인 포인트: Query Planning 섹션에서 Iceberg 메타데이터를 읽어오는 데 걸린 시간과 읽어온 정보의 종류를 확인할 수 있습니다.
방법 C: Iceberg 메타데이터 테이블 직접 조회
Iceberg 테이블 자체에 상세 통계가 저장되어 있는지 확인합니다.
sql
-- 테이블명 뒤에 $files를 붙여 조회
SELECT column_sizes, value_counts, null_value_counts, lower_bounds, upper_bounds
FROM <catalog>.<db>.<table_name>$files;
* 여기서 lower_bounds, upper_bounds 등이 비어있거나 `null`이라면, Iceberg 자체에 StarRocks가 활용할 수 있는 통계가 없는 상태입니다.
요약 가이드
1. 계획 동일성 확인: `EXPLAIN COSTS`를 통해 cardinality 수치가 변하는지 확인하십시오. 수치가 변하지 않는다면 옵션이 작동하지 않는 것이 아니라, 읽어올 통계(Puffin 파일 등)가 Iceberg 측에 없는 것입니다.
2. 데이터 소스 확인: Iceberg 측에서 통계 수집 시 `NDV`를 포함하는 Puffin 파일을 생성하도록 설정되어 있는지 확인해 보시기 바랍니다.
References
• sql-reference/System_variable.md (enable_iceberg_column_statistics 설명 참조)
• data_source/catalog/iceberg/iceberg_catalog.md
• using_starrocks/Cost_based_optimizer.md
References
• sql-reference/System_variable.md
• data_source/catalog/iceberg/iceberg_catalog.md
• using_starrocks/Cost_based_optimizer.md
References
• sql-reference/System_variable.md
• data_source/feature-support-data-lake-analytics.md
• data_source/catalog/iceberg/iceberg_catalog.md
• using_starrocks/Cost_based_optimizer.mdRonJay
09/30/2026, 6:26 AMRocky
09/30/2026, 6:26 AM_statistics_.loads_history 테이블에 대해 ALTER TABLE ... DROP PARTITION 명령을 실행할 때 발생하는 "NO viable statement for input 'DROP PARTITION 34529'" 에러는 주로 문법 오류(Syntax Error) 때문입니다.
성공적인 명령 실행을 위해 다음 사항들을 확인해 주십시오.
1. 파티션 이름(Name)과 ID(ID)의 구분
StarRocks에서 DROP PARTITION 뒤에는 *파티션의 이름(Partition Name)*이 와야 합니다. 사용자가 입력하신 `34529`는 파티션 이름이 아닌 시스템 내부의 *Partition ID*일 가능성이 매우 높습니다.
* 먼저 정확한 파티션 이름을 확인하십시오:
sql
SHOW PARTITIONS FROM _statistics_.loads_history;
* 조회된 결과의 PartitionName 컬럼 값을 사용해야 합니다. (보통 내부 관리용 파티션은 `p20240925`와 같은 형식으로 생성됩니다.)
2. 문법 수정
파티션 이름이 숫자로만 되어 있더라도 식별자로 인식되어야 하므로, 만약 이름이 정말 `34529`라면 *백틱(`)*으로 감싸거나 올바른 식별자 규칙을 따라야 합니다. 하지만 기본적으로 StarRocks의 문법은 다음과 같습니다.
sql
-- 올바른 문법 예시
ALTER TABLE _statistics_.loads_history DROP PARTITION p20240925;
3. 권장 방법: 자동 관리 (Retention 설정)
`_statistics_.loads_history`는 StarRocks의 내부 시스템 테이블로, 수동으로 파티션을 삭제하기보다는 *FE 설정값*을 통해 자동으로 관리하는 것이 권장됩니다.
* 보관 주기 변경 (Global 설정):
데이터가 너무 많이 쌓여 삭제하려는 것이라면, FE의 loads_history_retained_days 설정을 변경하여 자동 삭제되도록 할 수 있습니다. (기본값 30일, v3.3.6+ 지원)
sql
ADMIN SET FRONTEND CONFIG ("loads_history_retained_days" = "14");
요약
1. SHOW PARTITIONS FROM _statistics_.loads_history; 명령으로 *PartitionName*을 먼저 확인하세요.
2. DROP PARTITION 뒤에 확인한 *이름*을 넣으세요. (숫자 형태의 ID를 넣으면 위와 같은 구문 에러가 발생합니다.)
3. 가급적 FE 설정을 통한 자동 관리를 권장합니다.
References
• sql-reference/sql-statements/table_bucket_part_index/ALTER_TABLE.md
• administration/management/FE_configuration.md
• loading/loading_introduction/troubleshooting_loading.md
References
• loading/loading_introduction/troubleshooting_loading.md
• administration/management/FE_configuration.md
• using_starrocks/Cost_based_optimizer.md
• administration/management/monitoring/metrics.md
• sql-reference/sql-statements/cbo_stats/DROP_STATS.mdRonJay
10/01/2026, 5:40 AMRocky
10/01/2026, 5:40 AMANALYZE 명령을 통해 외부 테이블의 통계를 수집했다면 내부 통계 테이블에 저장됩니다.
* 명령어 사용:
sql
SHOW STATS <iceberg_table_name>;
* 직접 조회:
sql
SELECT * FROM _statistics_.external_column_statistics
WHERE table_name = '테이블명';
* 데이터가 조회된다면 StarRocks가 자체적으로 관리하는 통계 정보가 있는 것입니다. 만약 질문자님처럼 통계를 모두 삭제하셨다면 여기서 결과가 나오지 않아야 정상입니다.
──────────
2. Iceberg 메타데이터 파일 확인 (External Metadata)
Iceberg 자체에 통계 정보(Min/Max, Null Count 등)가 있는지 확인하려면 Iceberg의 메타데이터 테이블을 조회해야 합니다.
* 파일 정보 조회:
sql
SELECT * FROM <catalog>.<db>.<table_name>$files;
* 확인할 컬럼:
* lower_bounds, `upper_bounds`: 컬럼별 최소/최대값 정보 (바이너리 형태)
* `null_value_counts`: Null 개수
* `value_counts`: 전체 값 개수
* 이 컬럼들이 `null`이거나 비어있다면 Iceberg 자체에 컬럼 통계가 생성되지 않은 상태입니다.
──────────
3. 옵티마이저가 사용하는 통계 확인 (EXPLAIN)
사용자가 설정한 옵션들이 실제로 적용되어 옵티마이저가 통계를 인지하고 있는지 확인하는 가장 확실한 방법입니다.
* EXPLAIN COSTS 실행:
sql
EXPLAIN COSTS
SELECT * FROM <iceberg_table_name> WHERE <컬럼명> = '값';
* 결과 해석:
* 결과 상단의 Estimates 또는 각 연산자(Iceberg Scan 등)의 cardinality 수치를 확인하세요.
* 통계가 없는 경우: `cardinality`가 1, 100, 또는 전체 행 수와 무관한 기본값(Default)으로 표시됩니다. column statistics 항목에 `UNKNOWN`이 나타날 수 있습니다.
* 통계가 있는 경우: `cardinality`가 조건절에 따라 계산된 수치로 표시되며, `column statistics`에 특정 컬럼의 ndv, range 정보가 구체적으로 출력됩니다.
──────────
4. NDV(Puffin) 통계 유무 확인 (고급)
enable_iceberg_column_statistics 옵션이 사용하는 NDV(Puffin 파일) 정보가 있는지 확인하려면 Iceberg의 snapshots 메타데이터를 확인해야 합니다.
sql
SELECT * FROM <catalog>.<db>.<table_name>$snapshots;
* summary 컬럼 내에 Puffin 파일 관련 정보가 포함되어 있는지, 혹은 별도의 통계 수집 프로세스가 Iceberg 쪽에서 실행된 적이 있는지 확인이 필요합니다.
요약
가장 먼저 *`EXPLAIN COSTS <쿼리>`*를 실행하여 `cardinality`와 `column statistics`가 출력되는지 확인하십시오. 만약 여기서 통계 정보가 보이지 않는다면, $files 메타데이터 조회를 통해 Iceberg 원본에 데이터가 있는지 검증하는 순서로 확인하시는 것이 좋습니다.
References
• data_source/catalog/iceberg/iceberg_catalog.md
• using_starrocks/Cost_based_optimizer.md
• sql-reference/sql-statements/cbo_stats/SHOW_STATS.md