RonJay
07/13/2026, 2:29 AMRocky
07/13/2026, 2:30 AMiceberg.catalog.security = "oauth2", StarRocks utilizes the standard Iceberg REST client logic.
* Trigger: If iceberg.catalog.oauth2-token-refresh-enabled is set to true (it is often true by default in the Java client), the client automatically manages token expiration.
* Mechanism: The Iceberg REST client tracks the expires_in value returned by Polaris during the initial token exchange (triggered by iceberg.catalog.oauth2.credential).
* Background Execution: The client uses an internal ScheduledExecutorService to refresh the token before it expires. It will attempt to use a refresh_token if provided by Polaris, or re-exchange the client_id and client_secret to obtain a new access token.
* Configuration Example:
sql
CREATE EXTERNAL CATALOG polaris_catalog
PROPERTIES (
"type" = "iceberg",
"iceberg.catalog.type" = "rest",
"iceberg.catalog.uri" = "http://<polaris-host>:8181/api/catalog",
"iceberg.catalog.security" = "oauth2",
"iceberg.catalog.oauth2.credential" = "client_id:client_secret",
"iceberg.catalog.oauth2-token-refresh-enabled" = "true"
);
3. StarRocks Background Metadata Refresh
To ensure StarRocks "perceives" new data committed to Polaris without requiring a manual REFRESH command, StarRocks runs a background thread on the Frontend (FE).
* Mechanism: The FE periodically calls the Polaris REST API to check the latest metadata locations and snapshots for frequently accessed tables.
* Parameters:
* `enable_background_refresh_connector_metadata`: Set to true (default in v3.0+) to enable this polling.
* `background_refresh_metadata_interval_millis`: Controls how often the refresh occurs (default is 10 minutes).
* `background_refresh_metadata_time_secs_since_last_access_secs`: StarRocks only refreshes metadata for catalogs that have been accessed within this window (default 24 hours) to save resources.
4. JWT Identity Passthrough (StarRocks 4.0+)
In the latest versions, StarRocks supports a Catalog-Centric model. If you use iceberg.catalog.security = "jwt", StarRocks does not manage a background "service" token. Instead:
* The user's own JWT (from their StarRocks login) is passed directly to Polaris for every request.
* In this mode, there is no "background refresh" for the token by StarRocks; if the user's session token expires, they must re-authenticate with StarRocks.
Summary of Logic for Polaris
Feature | Implementation | Key Property
OAuth2 Token | Managed by the Iceberg Java Client; re-exchanges credentials/refresh tokens automatically. | iceberg.catalog.oauth2-token-refresh-enabled
Table Metadata | Managed by StarRocks FE background thread; polls Polaris for new snapshots. | enable_background_refresh_connector_metadata
Vended Credentials | Temporary storage tokens (S3/ADLS) are fetched by StarRocks for each IO task. | iceberg.catalog.vended-credentials-enabled
References
• data_source/catalog/iceberg/iceberg_rest_security.md
• data_source/catalog/iceberg/iceberg_catalog.mdRonJay
07/13/2026, 2:43 AMRocky
07/13/2026, 2:44 AMsplit_part and substring_index.
1. split_part
This function is available in StarRocks. It splits a string by a delimiter and returns the specific part requested.
* Syntax: split_part(content, delimiter, field)
* Note: The field parameter can be a positive integer (counting from the beginning) or a negative integer (counting from the end).
* Example:
sql
SELECT split_part("hello world", " ", 1); -- Returns "hello"
SELECT split_part("a.b.c", ".", -1); -- Returns "c"
2. substring_index
This function is supported starting from StarRocks v3.2. It mimics the behavior of the MySQL function by returning a substring that precedes or follows the n-th occurrence of a delimiter.
* Syntax: substring_index(str, delimiter, count)
* Example:
sql
-- Returns substring before the second "."
SELECT substring_index('<http://www.starrocks.io|www.starrocks.io>', '.', 2); -- Returns "www.starrocks"
-- Returns substring after the second "." from the right
SELECT substring_index('<http://www.starrocks.io|www.starrocks.io>', '.', -2); -- Returns "<http://starrocks.io|starrocks.io>"
Alternative Options
If you are on a version earlier than 3.2 and need the behavior of substring_index, or if you need more complex splitting, you can use:
* split() + Array indexing: split("a.b.c", ".")[1] (Note: StarRocks array indices start at 1).
* `regexp_extract()`: For complex patterns where simple delimiters aren't enough.
* `regexp_split()`: Splits a string into an array based on a regular expression.
References
• sql-reference/sql-functions/string-functions/split_part.md
• sql-reference/sql-functions/string-functions/substring_index.md
References
• sql-reference/sql-functions/string-functions/split_part.md
• sql-reference/sql-functions/string-functions/substring_index.md
• sql-reference/sql-functions/string-functions/split.md
• sql-reference/sql-functions/string-functions/substring.md
• sql-reference/sql-functions/string-functions/field.md
• sql-reference/sql-functions/string-functions/find_in_set.md
• sql-reference/sql-functions/string-functions/regexp_split.md
• sql-reference/sql-functions/string-functions/parse_url.mdRonJay
07/13/2026, 2:47 AMRocky
07/13/2026, 2:48 AMSELECT 1 and a heavy join as equal "concurrency." | Fine-grained. Heavy queries occupy more slots than light queries.
Enabling | Enabled by enable_query_queue_select = true. | Enabled by FE config enable_query_queue_v2 = true.
──────────
2. Does v1 consider Query/CN status?
The answer is yes, but with limitations. It is incorrect to say v1 does not consider status, but its method is less "real-time" and less "proactive" than v2.
Query Status in v1:
* Versions < v3.1.4: The status (number of running queries) was reported by BEs to the FE periodically (default 1 second). This caused a delay. If 50 queries arrived in a single second, the FE might let them all through before receiving a "full" status report from the BE.
* Versions ≥ v3.1.4: StarRocks introduced Collective Concurrency Management. The Leader FE now tracks query starts/ends in real-time across all Follower FEs. This fixed the "query status" delay issue even in v1.
CN (Compute Node) Status in v1:
* v1 monitors CN status via query_queue_cpu_used_permille_limit and query_queue_mem_used_pct_limit.
* However, v1 is reactive: it only starts queuing after the CN/BE reports it is already over the CPU/Memory threshold.
* v2 is proactive: Because v2 uses a "Slot Manager" on the FE, it knows the total slot capacity of the CNs and won't dispatch a query if the required slots aren't available, preventing the CN from ever hitting an "overloaded" status in the first place.
Summary
* Query Queue v1 is best for simple concurrency capping.
* Query Queue v2 (Recommended for v3.3+) is better for complex workloads because it uses resource estimation and slot management to prevent node overload before it happens.
References
• administration/management/resource_management/query_queues.md
• administration/management/FE_configuration.md
References
• administration/management/FE_configuration.md
• administration/management/resource_management/query_queues.md
• sql-reference/System_variable.mdRonJay
07/13/2026, 8:34 AMRocky
07/13/2026, 8:35 AMERROR: For input string: "1024819115206086140.000" is a Java NumberFormatException. It occurs when StarRocks tries to parse a string as a numeric integer (like a Long), but the string contains a decimal point (.000) or is not a valid number.
This typically happens for one of the following reasons:
1. Using the Wrong ID (Connection ID vs. Query ID)
The ANALYZE PROFILE command requires the Query ID (a UUID string), not the Connection ID (a numeric integer).
* Connection ID: A number like 10248 (found in SHOW PROCESSLIST).
* Query ID: A UUID string like a40456b2-8428-11ee-8d02-6a32f8c68848 (found in SHOW PROFILELIST).
If you are copying the ID from a tool like DBeaver or Excel, those tools often format large numbers by adding .000 or using scientific notation, which causes the parsing error.
2. Missing Single Quotes
The syntax for ANALYZE PROFILE requires the Query ID to be wrapped in single quotes (').
* Incorrect: ANALYZE PROFILE FROM 1024819115206086140.000 (Parsed as a numeric literal)
* Incorrect: ANALYZE PROFILE FROM "1024819115206086140.000" (Double quotes are for identifiers like column names)
* Correct: ANALYZE PROFILE FROM 'a40456b2-8428-11ee-8d02-6a32f8c68848'
3. Mismatched Node ID
If you are specifying a Plan Node ID (e.g., ANALYZE PROFILE FROM 'uuid', 1), ensure the node ID is a simple integer. If your client tool manges the node ID to 1.000, it will trigger this error.
──────────
How to fix it:
1. Find the correct Query ID:
Run this command to see the list of recent queries and their actual IDs:
sql
SHOW PROFILELIST;
2. Copy the UUID string:
Look for the string in the QueryId column (e.g., 5f0d3b6a-9f7a-11ee-8e91-00163e123456).
3. Run the analysis with single quotes:
sql
-- Replace the example UUID with your actual QueryId
ANALYZE PROFILE FROM '5f0d3b6a-9f7a-11ee-8e91-00163e123456';
Tip: If you just ran the query you want to analyze, you can get the ID immediately using:
sql
SELECT last_query_id();
References
• sql-reference/sql-statements/cluster-management/plan_profile/ANALYZE_PROFILE.md
• sql-reference/sql-statements/cluster-management/plan_profile/SHOW_PROFILELIST.md
References
• sql-reference/sql-statements/cluster-management/plan_profile/ANALYZE_PROFILE.md
• best_practices/query_tuning/query_profile_text_based_analysis.md
• loading/loading_introduction/troubleshooting_loading.mdRonJay
07/13/2026, 8:50 AMRocky
07/13/2026, 8:50 AMnow(), curdate() 같은 함수가 포함되어 있어, 시간이 흐름에 따라 검색 대상 파티션 범위가 넓어지지 않았는지 확인하세요.
* 데이터 타입 불일치: 만약 쿼리에서 변수를 사용한다면, 변수의 타입이 파티션 컬럼과 맞지 않아 *Implicit Cast(암시적 형변환)*가 발생하면 파티션 프루닝이 작동하지 않을 수 있습니다.
3. 데이터 중첩 및 인덱스(Zone Map) 효율 저하
StarRocks는 각 데이터 블록의 Min/Max 값을 저장하는 Zone Map 인덱스를 사용합니다.
* 데이터 겹침: 데이터가 정렬되지 않은 상태로 계속 들어오면(예: 과거 날짜 데이터가 계속 섞여 들어옴), 각 세그먼트의 Min/Max 범위가 서로 겹치게 됩니다. 이 경우 필터 조건으로 데이터를 거르지 못하고 더 많은 블록을 스캔하게 됩니다.
* 해결: 해당 테이블에 대해 `Compaction`이 정상적으로 수행되었는지 확인하거나, 자주 조회되는 컬럼으로 `ORDER BY`를 설정하여 데이터를 재정렬하는 것이 도움이 됩니다.
4. 태블릿(Tablet) 및 세그먼트(Segment) 파편화
데이터가 아주 작은 단위로 자주 적재(Stream Load 등)되면 수많은 작은 파일(Segment)이 생성됩니다.
* 파일이 너무 많아지면 메타데이터 읽기 비용과 스캔 효율이 급격히 떨어집니다.
* 체크: `SHOW TABLET FROM <table_name>`을 통해 태블릿 상태를 확인하고, BE 로그에서 Compaction 관련 경고가 없는지 확인하세요.
5. 실행 계획(Execution Plan)의 변화
데이터 통계 정보가 업데이트되면서 Optimizer가 다른 인덱스를 선택하거나, 조인 순서를 바꾸면서 특정 테이블을 더 많이 스캔하게 될 수 있습니다.
* 해결: `EXPLAIN ANALYZE <query>`를 실행하여 ScanNode 부분의 `RowsRead`와 `BytesRead`를 이전 프로파일과 비교해 보세요. 어떤 노드에서 급격히 늘어났는지 알 수 있습니다.
──────────
추천 대응 단계
1. 프로파일 분석: `ANALYZE PROFILE FROM 'query_id';`를 통해 어떤 `OLAP_SCAN_NODE`에서 데이터 스캔이 많이 발생하는지 확인합니다.
2. 파티션 확인: `EXPLAIN <query>`를 실행하여 partitions 항목에 불필요한 파티션까지 포함되어 있는지 확인합니다.
3. 통계 업데이트: `ANALYZE TABLE <table_name> WITH SYNC;`를 통해 통계 정보를 최신화하여 최적의 실행 계획을 유도합니다.
만약 위 사항들을 확인해도 원인이 불분명하다면, *최근에 테이블 스키마 변경(Schema Change)이나 세션 변수 변경*이 있었는지 검토해 보시기 바랍니다.
References
• administration/management/monitoring/metrics.md
• best_practices/query_tuning/query_profile_text_based_analysis.md
• faq/Sql_faq.md
References
• loading/loading_introduction/troubleshooting_loading.md
• best_practices/query_tuning/query_profile_text_based_analysis.mdRonJay
07/15/2026, 4:31 AMRocky
07/15/2026, 4:31 AMmem_limit): 해당 리소스 그룹에 속한 *모든 쿼리가 사용하는 메모리의 합계*가 이 한도를 넘을 수 없습니다. (예: BE 전체 메모리의 30%)
* 그룹 내 개별 쿼리 한도 (query_mem_limit): 리소스 그룹 설정 내에 `query_mem_limit`이 지정되어 있다면, 해당 그룹의 쿼리 하나가 쓸 수 있는 최대 메모리가 됩니다.
* 설정 예시: CREATE RESOURCE GROUP group_name WITH ("mem_limit" = "30%", "query_mem_limit" = "2G");
2. 세션 변수 (query_mem_limit)
사용자가 `SET query_mem_limit = 8G;`와 같이 세션 변수를 설정한 경우입니다.
* 리소스 그룹 내에 개별 쿼리 한도가 설정되어 있지 않다면, 이 세션 변수 값이 개별 쿼리의 최대 메모리 사용량이 됩니다.
* 단, 세션 변수 값이 리소스 그룹의 전체 `mem_limit`보다 크더라도, 그룹 전체의 합계 한도는 넘을 수 없습니다.
3. 상호작용 우선순위 요약
구분 | 적용 대상 | 특징
리소스 그룹 mem_limit | 그룹 전체 합계 | 가장 강력한 물리적 제어. 그룹 내 쿼리가 많으면 개별 쿼리가 `query_mem_limit`에 도달하기 전에 그룹 한도에 걸려 대기하거나 실패할 수 있습니다.
리소스 그룹 query_mem_limit | 개별 쿼리 | 해당 그룹에 속한 쿼리 하나당 최대치. 세션 변수보다 우선순위가 높게 설정될 수 있습니다.
세션 변수 query_mem_limit | 개별 쿼리 | 사용자가 쿼리 단위로 제어하는 값. 리소스 그룹 설정이 없으면 이 값을 따릅니다.
BE mem_limit | 노드 전체 | 시스템의 최종 물리 한도.
요약하자면
리소스 그룹의 설정을 우선적으로 따릅니다.
리소스 그룹은 동시 쿼리가 수행될 때 특정 서비스나 사용자가 전체 시스템 메모리를 독점하지 못하도록 물리적으로 격리하는 역할을 하기 때문입니다. 만약 리소스 그룹을 설정했다면, `mem_limit`(그룹 합계)과 `query_mem_limit`(개별 쿼리)이 쿼리 실행의 기준점이 됩니다.
참고: StarRocks v3.x 이상의 *리소스 그룹 v2*에서는 메모리가 부족할 때 중요도가 낮은 그룹의 메모리를 회수하거나, 설정에 따라 디스크 스필링(Spilling)을 유도하여 쿼리가 실패하지 않고 완주하도록 돕는 기능도 포함되어 있습니다.
References
• administration/management/resource_management/resource_group.md
• sql-reference/sql-statements/cluster-management/resource_group/CREATE_RESOURCE_GROUP.md
• sql-reference/System_variable.md
References
• administration/management/resource_management/resource_group.md
• sql-reference/sql-statements/cluster-management/resource_group/CREATE_RESOURCE_GROUP.md
• administration/management/resource_management/query_queues.md
• sql-reference/System_variable.md
• administration/management/FE_configuration.md
• faq/Sql_faq.md
• administration/management/monitoring/metrics.md
• metrics.md)
• administration/management/BE_configuration.md
• loading/loading_introduction/troubleshooting_loading.md
• best_practices/query_tuning/query_profile_text_based_analysis.md
• sql-reference/sql-statements/cluster-management/plan_profile/ANALYZE_PROFILE.md
• sql-reference/sql-statements/cluster-management/plan_profile/SHOW_PROFILELIST.mdRonJay
07/15/2026, 6:06 AMRocky
07/15/2026, 6:06 AMconcurrency_limit)
가장 권장되는 방법입니다. 특정 사용자나 애플리케이션이 사용하는 리소스 그룹에 최대 동시 실행 쿼리 수를 지정할 수 있습니다.
* 설정 방법:
sql
ALTER RESOURCE GROUP group_name WITH ("concurrency_limit" = "20");
* 동작: 해당 그룹에서 실행 중인 쿼리가 20개를 넘으면, 이후 들어오는 쿼리는 대기(Queue) 상태가 되거나 설정에 따라 실패 처리됩니다.
2. 전역 동시성 제한 (Global Query Queue)
리소스 그룹과 관계없이 BE(Backend) 노드당 실행될 수 있는 전체 동시 쿼리 수를 제한합니다.
* 설정 변수: query_queue_concurrency_limit
* 설정 방법:
sql
SET GLOBAL query_queue_concurrency_limit = 100;
* 특징: 이 값이 `0`보다 크면 전역 쿼리 대기열 기능이 활성화되며, 시스템 전체의 동시성을 제어합니다.
3. 사용자별 최대 연결 수 (max_user_connections)
특정 사용자가 동시에 맺을 수 있는 세션(연결) 수를 제한하여 간접적으로 동시성을 제어합니다.
* 설정 방법:
sql
ALTER USER 'username' SET PROPERTIES ("max_user_connections" = "50");
4. FE 설정 (고급 설정)
FE(Frontend)의 `fe.conf`에서 시스템 전체의 스케줄링 및 큐 관련 파라미터를 조정할 수 있으나, 일반적인 서비스 운영 시에는 위 1, 2번(리소스 그룹 및 세션 변수)을 사용하는 것이 훨씬 유연합니다.
* `query_queue_v2_concurrency_level`: (v3.1.4+) 시스템의 전체 쿼리 슬롯 계산에 영향을 주는 논리적 설정값입니다.
──────────
요약
Internal Catalog에 대한 동시 쿼리 제한을 원하신다면:
1. *리소스 그룹*을 생성하여 사용자를 할당하고,
2. 해당 그룹에 *`concurrency_limit`*을 설정하는 것이 가장 효과적입니다.
외부 카탈로그(JDBC, Hive 등)와 달리 Internal Catalog는 StarRocks 자체 리소스를 직접 사용하므로, 위와 같은 리소스 격리(Resource Isolation) 메커니즘이 곧 동시성 제한 설정이 됩니다.
References
• administration/management/resource_management/query_queues.md
• administration/management/resource_management/resource_group.md
• administration/management/resource_management/Query_management.md
• sql-reference/System_variable.md
• administration/management/FE_configuration.md
References
• administration/management/FE_configuration.md
• administration/management/resource_management/query_queues.mdRonJay
07/15/2026, 11:31 PMRocky
07/15/2026, 11:31 PMmalloc 대신 성능과 확장성이 뛰어난 *jemalloc*을 사용합니다.
* 역할: OS로부터 메모리 블록을 가져와 쿼리나 부하(Load) 작업에 필요한 미세한 단위로 쪼개어 할당합니다.
* 특징: 멀티코어 환경에서 잠금(Lock) 경합을 최소화하고 메모리 파편화(Fragmentation)를 방지하는 데 최적화되어 있습니다.
* Metadata 추적: jemalloc 자체가 관리 목적으로 사용하는 메모리(stats.metadata)가 있는데, 최신 StarRocks(v3.2.12+)에서는 이 오버헤드까지 `MemTracker`에서 추적하여 메모리 계산의 정확도를 높였습니다.
2. MemTracker: 논리적 메모리 회계사 (The Accountant)
StarRocks 내부에서 "누가 메모리를 얼마나 쓰고 있는가"를 계층적으로 기록하는 도구입니다.
* 계층 구조 (Hierarchy):
* Root MemTracker: BE 프로세스 전체의 합계.
* Category MemTracker: `query_pool`(쿼리), `load`(적재), `table_meta`(메타데이터), `page_cache`(캐시) 등으로 분류.
* Instance MemTracker: 개별 Query ID나 Load ID 단위로 세분화된 추적.
* 동작 방식: 데이터 구조가 생성될 때(예: Join용 Hash Table 생성) MemTracker에 "이만큼 쓰겠다"고 등록(Consume)하고, 해제될 때 해제(Release)를 보고합니다. 이를 통해 어떤 쿼리가 범인인지 정확히 찾아낼 수 있습니다.
3. Process Memory & Limits (제한 정책)
BE 설정 파일(be.conf)의 mem_limit 파라미터를 기준으로 시스템을 보호합니다.
* Hard Limit (기본 90%): 프로세스가 이 한도에 도달하면 메모리 부족(OOM)으로 판단합니다. StarRocks는 스스로를 보호하기 위해 메모리를 가장 많이 쓰는 쿼리를 강제 종료(Cancel) 시킵니다.
* Soft Limit (기본 80%): 이 선을 넘으면 StarRocks는 가용 메모리를 확보하기 위해 *가비지 컬렉션(GC)*을 시작합니다. 이때 캐시(Page Cache 등)를 우선적으로 비웁니다.
4. 전체적인 동작 흐름
1. 할당 요청: 쿼리 실행 중 대량의 데이터 처리가 필요하면 `jemalloc`에 메모리를 요청합니다.
2. 추적 업데이트: 동시에 해당 쿼리의 `MemTracker`와 `Root MemTracker`에 사용량이 기록됩니다.
3. 한도 체크:
* 만약 `Root MemTracker`가 *Soft Limit*을 넘으면, 백그라운드 스레드가 동작하여 불필요한 캐시를 해제합니다.
* 만약 *Hard Limit*을 넘거나, 개별 쿼리가 설정된 `query_mem_limit`을 초과하면 해당 쿼리는 Memory Limit Exceeded 에러와 함께 중단됩니다.
4. 메모리 반환: 쿼리가 끝나면 `MemTracker`에서 수치가 빠지고, `jemalloc`은 해당 메모리를 들고 있다가 필요시 OS에 반환합니다.
5. 모니터링 방법
실시간으로 메모리 구조를 확인하고 싶다면 BE 노드의 HTTP 엔드포인트를 활용할 수 있습니다.
* 전체 통계: http://<be_ip>:<be_http_port>/mem_tracker
* 상세 분석: http://<be_ip>:<be_http_port>/memz (tcmalloc/jemalloc의 상세 상태 확인)
요약하자면, jemalloc이 효율적으로 땅을 나누어 주고(물리 할당), MemTracker가 장부를 적으며(논리 추적), mem_limit 정책이 시스템이 뻗지 않도록 관리하는 구조입니다.
References
• administration/management/resource_management/Memory_management.md
• administration/management/BE_configuration.md
• developers/jemalloc_heap_profile.md
References
• administration/management/resource_management/Memory_management.md
• administration/management/BE_configuration.md
• developers/jemalloc_heap_profile.md
• knowledge/trouble_shooting/fe_memory_problems.mdRonJay
07/15/2026, 11:46 PMRocky
07/15/2026, 11:46 PMreport_resource_usage_interval_ms 설정).
* 내용: `TResourceUsage`라는 구조체에 다음 정보를 담아 Master FE에게 보냅니다.
* 현재 사용 중인 메모리 양 및 한도 (MemTracker 수치 기반)
* CPU 사용률
* 현재 실행 중인 쿼리 개수 (NumRunningQueries)
* 리소스 그룹별 리소스 사용량
* 용도: FE는 이 데이터를 바탕으로 SHOW PROC '/backends' 또는 '/compute_nodes' 결과를 업데이트하고, 쿼리 스케줄링 시 어떤 노드가 한가한지 판단합니다.
2. 쿼리 실행 상태 보고 (Query Execution State Report)
개별 쿼리의 진행 상황이나 종료 여부는 RPC를 통해 실시간에 가깝게 전파됩니다.
* 메커니즘: BE/CN에서 쿼리 파편(Fragment)을 실행하는 ExecStateReporter 스레드가 FE에게 상태를 보냅니다.
* 내용:
* 쿼리 파편의 완료 여부
* 오류 발생 시 에러 메시지 및 상태 코드
* 부하(Load) 작업의 경우 진행률 및 프로파일 데이터
* 우선순위: 일반적인 상태 보고와 긴급한 오류 보고(Priority)를 위한 스레드 풀이 분리되어 있어, 노드에 부하가 많아도 쿼리 실패 정보는 빠르게 FE에 전달됩니다.
3. 하트비트 (Heartbeat)
FE가 노드의 생존 여부를 확인하는 가장 기본적인 방식입니다.
* 방향: FE → BE/CN (요청) / BE/CN → FE (응답)
* 내용: 해당 노드가 살아있는지(Alive), 버전이 무엇인지, RPC 포트가 열려있는지 등을 확인합니다.
* 결과: 만약 하트비트 응답이 없으면 FE는 해당 노드를 'Dead' 상태로 표시하고, 쿼리 대상에서 제외(Blacklist)하거나 데이터 복구(Replication)를 계획합니다.
4. 기타 통계 리포트
그 외에 데이터의 상태와 관련된 정보들은 조금 더 긴 주기로 전파됩니다.
* Tablet Report: 각 노드가 가진 데이터 복제본(Tablet)의 최신 버전 정보를 약 60초마다 보고합니다.
* Disk State Report: 디스크 잔여 용량 정보를 약 60초마다 보고합니다.
요약
정보 종류 | 전파 주체 | 전파 방식 | 주기
생존 여부 | FE → BE/CN | Heartbeat | 수 초 단위
메모리/CPU/쿼리수 | BE/CN → FE | Resource Report | 1초 (기본값)
쿼리 성공/실패 | BE/CN → FE | Async RPC (Report) | 실시간 (이벤트 발생 시)
데이터(Tablet) 상태 | BE/CN → FE | Tablet Report | 60초 (기본값)
결과적으로 FE는 각 노드로부터 1초마다 들어오는 리포트를 통해 클러스터 전체의 "메모리 지도"와 "부하 지도"를 실시간으로 관리하게 됩니다.
References
• administration/management/BE_configuration.md
• administration/management/FE_configuration.md
• deployment/deploy_manually.md
• administration/management/BE_blacklist.md
References
• administration/management/BE_configuration.md
• administration/management/FE_configuration.md
• deployment/deploy_manually.md
• administration/management/BE_blacklist.md
References
• administration/management/BE_configuration.md
• administration/management/BE_blacklist.md
• administration/management/FE_configuration.md
• deployment/deploy_manually.mdRonJay
07/15/2026, 11:48 PMRocky
07/15/2026, 11:49 PMAlive: true)를 가장 먼저 확인합니다. 하트비트가 끊기면 해당 노드는 즉시 스케줄링 대상에서 제외(Blacklist)됩니다.
* 리소스 부하 상태 (Resource Report):
* 노드(BE/CN)는 1초마다 자신의 현재 부하 상태(실행 중인 쿼리 수, 메모리 사용량, CPU 사용률)를 FE에게 보고합니다.
* 쿼리 대기열(Query Queue) 적용: 만약 노드의 메모리나 CPU가 설정된 임계치(query_queue_mem_used_pct_limit 등)를 초과했다면, FE는 해당 노드에 새로운 쿼리를 바로 던지지 않고 큐에서 대기시키거나 다른 한가한 노드를 찾습니다.
──────────
2. 몇 개의 노드(CN/BE)를 쓸지는 어떻게 결정하는가?
쿼리 실행 시 몇 개의 노드를 투입할지는 *데이터의 위치*와 *사용자 설정 변수*에 따라 결정됩니다.
A. 내부 테이블 (Internal Table)의 경우
* 데이터 로컬리티 (Data Locality): 내부 테이블은 데이터가 특정 BE들에 분산 저장되어 있습니다. 따라서 해당 데이터(Tablet/Bucket)를 가지고 있는 BE들이 우선적으로 선택됩니다.
* 복제본 활용: 동일한 데이터의 복제본(Replica)이 여러 BE에 있다면, FE는 그중 부하가 가장 적은 BE를 선택하여 쿼리를 배분합니다.
B. 외부 카탈로그 및 Shared-data (CN 활용)의 경우
CN은 데이터가 로컬에 없으므로(S3/HDFS 등 사용), FE가 더 유연하게 결정합니다.
* Consistent Hashing (일관된 해싱): 외부 파일(Hive, Iceberg 등)을 스캔할 때, FE는 파일 경로를 해싱하여 특정 CN에 할당합니다. 이는 CN의 로컬 캐시 히트율을 높이기 위함입니다.
* 제어 변수:
* `prefer_compute_node`: `true`로 설정하면 쿼리 계산 시 BE보다 CN을 우선적으로 사용합니다.
* `use_compute_nodes`: 사용할 CN의 개수를 지정합니다.
* -1 (기본값): 가용한 모든 CN을 사용합니다.
* N (양수): 최대 N개의 CN만 쿼리에 참여시킵니다.
* Scan Range 분할: 데이터 스캔 범위(Scan Range)가 100개인데 CN이 10대라면, 보통 노드당 10개씩 할당됩니다. 하지만 데이터 양이 너무 적으면 노드를 다 쓰지 않고 일부만 사용하기도 합니다.
──────────
3. 요약: FE의 스케줄링 흐름
1. 계획 단계: CBO(최적화기)가 쿼리를 분석하여 데이터가 어디에 있는지, 얼마나 많은 연산이 필요한지 계산합니다.
2. 노드 필터링: Alive 상태이고 리소스 여유가 있는 노드 목록을 뽑습니다.
3. 할당 (Mapping):
* 내부 테이블 → 데이터가 있는 BE 노드 선택.
* 외부 데이터 → 해싱 알고리즘 및 use_compute_nodes 설정에 따라 CN 노드 선택.
4. 전달: 최종 결정된 노드들에게 RPC를 통해 "이 쿼리 조각을 실행하라"고 명령을 보냅니다.
즉, *"데이터가 어디에 있는가"*가 1순위 결정 요인이며, 데이터 위치 제약이 없는 CN의 경우에는 *"시스템 설정(use_compute_nodes)과 캐시 효율"*을 기준으로 노드 개수를 결정합니다.
References
• administration/management/BE_configuration.md
• administration/management/resource_management/query_queues.md
• sql-reference/System_variable.md
• deployment/deploy_manually.md
References
• deployment/deploy_manually.md
• administration/management/BE_configuration.md
• administration/management/resource_management/query_queues.md
• sql-reference/System_variable.md
• deployment/plan_cluster.md
References
• administration/management/BE_configuration.md
• administration/management/FE_configuration.md
• sql-reference/System_variable.md
• faq/resource_isolation_faq.mdRonJay
07/15/2026, 11:51 PMRocky
07/15/2026, 11:52 PMSHOW BACKENDS 명령어로도 확인할 수 있는 이 정보는 다음과 같습니다:
* DataCacheMetrics: 현재 캐시로 잡힌 디스크 사용량 (DiskUsage: 10GB/100GB)
* 캐시 상태: 정상(Normal)인지 혹은 디스크 오류 등으로 문제가 생겼는지 여부
4. 캐시 효율을 높이기 위한 추가 기능
* Cache Sharing (v3.1+): 만약 CN 1번이 죽어서 FE가 어쩔 수 없이 CN 2번으로 쿼리를 보냈을 때, CN 2번은 네트워크를 통해 CN 1번의 캐시가 남아있는지 확인하고 가져올 수 있습니다. (설정 필요)
* Data Cache Warmup: 사용자가 CACHE SELECT 명령을 내리면, FE는 해당 데이터를 담당하는 CN들에게 미리 데이터를 채워넣으라고 명령을 내릴 수도 있습니다.
요약
FE는 "어디에 무엇이 있는지" 일일이 목록을 보지 않습니다. 대신 *"이 데이터는 이 노드가 처리한다"는 규칙(Consistent Hashing)*을 사용하여 쿼리를 보내고, CN은 그 규칙에 따라 자기 캐시를 관리합니다. FE가 보는 리포트는 단지 그 노드의 캐시가 얼마나 꽉 찼는지와 같은 *전체적인 리소스 상태*일 뿐입니다.
References
• data_source/data_cache.md
• data_source/data_cache_observe.md
• deployment/shared_data/feature-support-shared-data.md
• introduction/Architecture.md
References
• data_source/data_cache.md
• data_source/data_cache_observe.md
• deployment/shared_data/feature-support-shared-data.md
• introduction/Architecture.md
• using_starrocks/caching/query_cache.md
References
• data_source/data_cache_observe.md
• using_starrocks/caching/query_cache.mdRonJay
07/15/2026, 11:54 PMRocky
07/15/2026, 11:54 PMRonJay
07/16/2026, 12:02 AMRocky
07/16/2026, 12:03 AMMemory Exceed Limit)가 발생하는 원인과 *v2(v3.1.4 이상 버전)*에서의 개선 사항은 다음과 같습니다.
1. Query Queue v1에서 메모리 초과가 발생하는 이유
v1 방식은 *"BE/CN의 사후 보고"*에 의존하기 때문입니다.
* 보고 지연 (Reporting Delay): v1에서는 CN이 자신의 리소스 상태(실행 중인 쿼리 수, 메모리 사용량)를 주기적(기본 1초, report_resource_usage_interval_ms)으로 FE에게 보고합니다.
* 폭주 대응 불가: 만약 1초라는 짧은 시간 사이에 수십 개의 쿼리가 동시에 들어오면, FE는 아직 CN이 "한가하다"고 판단하여 해당 노드로 쿼리를 계속 던집니다. CN은 보고를 채 하기도 전에 할당된 쿼리들을 처리하려다 메모리 임계치를 순식간에 넘겨버리게 됩니다.
* 일관된 해싱(Consistent Hashing)의 역효과: 외부 데이터 조회 시 캐시 효율을 위해 특정 CN에 쿼리를 집중시키는데, v1에서는 해당 노드의 부하가 FE에 실시간으로 반영되지 않아 특정 노드만 메모리 부족으로 터지는 현상이 잦습니다.
2. Query Queue v2 (v3.1.4+)에서 개선되는 점
v2 방식은 *"FE 중심의 전역 관리(Collective Concurrency Management)"*로 아키텍처가 바뀌었습니다.
* 실시간 카운팅: 쿼리가 시작될 때 FE가 즉시 카운트를 올리고, 끝날 때 내립니다. CN이 보고할 때까지 기다리지 않고 FE가 현재 몇 개의 쿼리가 어느 노드에서 도는지 *즉각적으로 파악*합니다.
* Leader FE 통합 관리: 여러 대의 FE를 사용할 경우에도 Leader FE가 전체 클러스터의 쿼리 상태를 통합 관리하므로, 여러 FE에서 동시에 한 노드로 쿼리를 몰아넣는 상황을 방지합니다.
* 메모리 예측 및 제어: v2는 단순히 실행 중인 쿼리 개수뿐만 아니라, 리소스 그룹(Resource Group) 단위의 메모리 제한과 연동되어 훨씬 정교하게 큐잉(Queueing)을 수행합니다.
3. 개선을 위한 권장 조치
만약 현재 버전에서 `Memory Exceed Limit`을 해결하고 싶다면 다음 설정을 검토하세요.
1. v3.1.4 이상으로 업그레이드: v2의 핵심 기능인 `Collective Concurrency Management`를 사용하려면 이 버전 이상이 필요합니다.
2. 리소스 그룹(Resource Group) 활용: 단순히 전역 큐(query_queue_mem_used_pct_limit)만 쓰지 말고, 리소스 그룹을 만들어 `concurrency_limit`과 `mem_limit`을 설정하세요. v2에서는 이 제한이 훨씬 엄격하고 실시간으로 작동합니다.
3. 임계치 조정: v1을 유지해야 한다면 query_queue_mem_used_pct_limit 값을 좀 더 보수적으로(예: 0.8 -> 0.6) 낮추어, 보고 지연 사이에 발생할 수 있는 메모리 서지를 대비할 공간을 확보해야 합니다.
요약하자면: v1은 CN이 "나 지금 바빠요"라고 말할 때까지 FE가 쿼리를 계속 보내서 발생하며, v2로 가면 FE가 "너 지금 바쁘니까 그만 보낼게"라고 스스로 판단하기 때문에 이 문제가 획기적으로 개선됩니다.
References
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.md
• administration/management/BE_configuration.md
• administration/management/resource_management/resource_group.md
• administration/http_interface/query_detail.md
References
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.md
• administration/management/BE_configuration.md
• administration/management/resource_management/resource_group.md
• administration/http_interface/query_detail.md
• deployment/shared_data/feature-support-shared-data.md
-data)
References
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.md
• administration/management/BE_configuration.mdRocky
07/16/2026, 12:03 AMRonJay
07/16/2026, 12:20 AMRocky
07/16/2026, 12:20 AMbig_query_cpu_second_limit 옵션에서 말하는 "빅쿼리"는 Google의 BigQuery 서비스가 아니라, *"리소스 소모가 큰 대규모 쿼리(Large/Heavy Query)"*를 의미합니다.
StarRocks가 이 쿼리가 "대규모"인지 미리 아는 것이 아니라, *실행 중에 실시간으로 리소스 사용량을 감시하다가 설정된 임계치를 넘으면 그 순간 "이것은 너무 큰 쿼리다"라고 판단하여 강제로 종료*시키는 방식입니다.
작동 방식과 판단 기준을 구체적으로 설명해 드리겠습니다.
1. 어떻게 동작하는가? (런타임 모니터링)
FE가 쿼리를 계획할 때 예측하는 것이 아니라, BE/CN(데이터 처리 노드)에서 실제 쿼리가 수행될 때 작동합니다.
* 실시간 추적: BE는 각 쿼리가 사용하는 CPU 시간(모든 병렬 태스크의 합계), 스캔한 행 수, 메모리 사용량을 실시간으로 카운트합니다.
* 임계치 체크: 쿼리가 실행되는 동안 수시로 해당 리소스 그룹(Resource Group)에 설정된 big_query_cpu_second_limit 값과 비교합니다.
* 강제 종료: 누적 CPU 사용 시간이 설정값을 초과하는 즉시 BE는 해당 쿼리를 실패(Cancel) 처리하고, "Big query exceeded limit"과 같은 에러 메시지를 반환합니다.
2. "빅쿼리"임을 판단하는 3가지 기준
StarRocks는 리소스 그룹 설정에서 다음 3가지 중 하나라도 초과하면 해당 쿼리를 리소스를 과다 점유하는 "큰 쿼리"로 간주합니다.
1. big_query_cpu_second_limit: 한 노드에서 쿼리가 사용한 총 CPU 시간(초)의 합계. (병렬 처리가 많을수록 빨리 도달함)
2. big_query_scan_rows_limit: 한 노드에서 이 쿼리가 읽어들인(Scan) 데이터의 총 행 수.
3. big_query_mem_limit: 한 노드에서 이 쿼리가 점유한 최대 메모리 양.
3. 왜 이런 옵션을 쓰나요?
특정 사용자나 서비스가 실수로 `SELECT *`를 하거나 조인 조건 없이 쿼리를 날렸을 때, *단 하나의 쿼리가 클러스터 전체의 CPU나 메모리를 다 써버려서 다른 서비스에 장애를 주는 것을 방지(Resource Isolation)*하기 위함입니다.
4. 설정 예시
이 설정은 보통 리소스 그룹(Resource Group) 단위로 적용합니다.
sql
ALTER RESOURCE GROUP 'adhoc_user_group' SET (
'big_query_cpu_second_limit' = '100', -- CPU 100초 이상 쓰면 차단
'big_query_scan_rows_limit' = '100000000' -- 1억 행 이상 읽으면 차단
);
요약
* 빅쿼리란? 리소스를 많이 쓰는 "무거운 쿼리"를 뜻함. (Google 서비스와 무관)
* 어떻게 아나? 미리 알지 못함. 실행 중에 실시간으로 사용량을 측정하다가 선을 넘으면 그 때 차단함.
* 효과: "악성 쿼리"가 클러스터 전체를 마비시키는 것을 방지함.
References
• administration/management/resource_management/resource_group.md
• faq/resource_isolation_faq.md
• administration/management/monitoring/metrics.md
• sql-reference/System_variable.md
References
• administration/management/resource_management/resource_group.md
• faq/resource_isolation_faq.md
• administration/management/monitoring/metrics.md
• sql-reference/System_variable.md
• administration/management/BE_configuration.md
• sql-reference/sql-statements/Account%20Management/ALTER_RESOURCE_GROUP.md
• sql-reference/sql-statements/Account%20Management/CREATE_RESOURCE_GROUP.md
References
• faq/resource_isolation_faq.md
• administration/management/resource_management/resource_group.md
• sql-reference/System_variable.md
• administration/management/monitoring/metrics.md
• administration/management/BE_configuration.mdRonJay
07/16/2026, 2:19 AMRocky
07/16/2026, 2:20 AMquery_queue_mem_used_pct_limit 등)에 도달했는지 매번 체크합니다.
2. 메모리가 꽉 차면 해당 노드를 안 쓰나요?
"안 쓰는 것"이 아니라 "비워질 때까지 쿼리를 대기(Queueing)" 시킵니다.
* 작동 방식: 특정 CN의 메모리 사용량이 설정한 퍼센트(예: 0.9 = 90%)를 넘으면, FE는 해당 CN으로 가야 할 신규 쿼리를 실행하지 않고 *큐(Queue)에 넣어서 대기*시킵니다.
* 이유 (중요): StarRocks는 데이터 캐시 효율을 위해 특정 데이터는 특정 CN이 처리하도록 지정(Consistent Hashing)합니다. 메모리가 꽉 찼다고 다른 한가한 노드로 쿼리를 바로 던져버리면, 캐시가 없는 노드에서 S3/HDFS 데이터를 새로 읽어야 하므로 전체 성능이 더 떨어질 수 있습니다. 그래서 *"조금 기다렸다가 캐시가 있는 노드에서 리소스가 나면 실행하자"*는 전략을 취합니다.
3. v2에서 메모리 관련 제어 방식
* `query_queue_mem_used_pct_limit`: 이 설정값(예: 0.8)을 기준으로, 특정 CN의 메모리가 80%를 넘으면 FE는 해당 노드를 대상으로 하는 쿼리들을 큐잉합니다.
* 거부(Reject) 조건: 만약 대기 중인 쿼리가 너무 많아져서 `query_queue_max_queued_queries`를 넘거나, query_queue_pending_timeout_second 시간이 지나면 쿼리는 실행되지 않고 실패 처리됩니다.
요약
* v1: 노드가 바쁜지 모르고 일단 던졌다가 CN에서 메모리 부족으로 터짐.
* v2: FE가 노드의 메모리 상태를 미리 알고, 꽉 차기 직전이면 쿼리를 보내지 않고 FE 단에서 줄을 세움.
따라서 v2를 쓰면 특정 노드가 메모리 초과로 죽는 현상을 방지하고, 시스템 전체의 안정성을 크게 높일 수 있습니다.
References
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.md
• administration/management/monitor_manage_big_queries.md
References
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.md
• administration/management/monitor_manage_big_queries.md
• administration/management/resource_management/resource_group.md
• table_design/data_distribution/Data_distribution.md
• administration/management/BE_blacklist.md
• administration/management/BE_configuration.md
• introduction/Architecture.md
• deployment/shared_data/feature-support-shared-data.md
• administration/management/monitoring/metrics.md
References
• administration/management/resource_management/query_queues.md
• administration/management/monitor_manage_big_queries.mdRonJay
07/16/2026, 4:13 AMRocky
07/16/2026, 4:14 AMpipeline_dop 설정에 따라 쿼리가 여러 개의 슬롯으로 쪼개집니다. CPU 코어가 32개일 때 슬롯을 32개로 잡으면 32개의 코어가 한꺼번에 달려들어 쿼리를 처리하므로 속도가 빨라집니다.
* 임계점: 슬롯 수(병렬도)가 CPU 코어 수보다 너무 많아지면, CPU는 실제 연산보다 작업 간 전환(Context Switching)에 더 많은 비용을 쓰게 되어 오히려 성능이 떨어집니다.
② Slot과 메모리의 관계 (병렬도 vs. 공간 부족)
* 상관관계: 슬롯(병렬도)이 늘어날수록 메모리 사용량은 선형적으로 증가합니다.
* 작동 원리: 예를 들어 Hash Join을 수행할 때, 슬롯이 10개라면 각 슬롯마다 데이터를 처리하기 위한 로컬 버퍼나 해시 테이블의 일부를 메모리에 올려야 합니다.
* 위험 요소: 쿼리 속도를 높이려고 `pipeline_dop`를 높게 설정하면, 동일한 데이터를 처리하더라도 동시에 점유하는 메모리 양이 급격히 늘어나 `Memory Exceed Limit`이 발생할 확률이 높아집니다.
③ 쿼리 동작(Query Execution) 간의 상관관계
쿼리가 들어오면 다음과 같은 순서로 자원이 얽힙니다.
1. Scheduling (Slot 할당): FE가 쿼리 계획을 세우고 BE/CN에 전달합니다. 이때 리소스 그룹의 `concurrency_limit`에 따라 실행 "슬롯"을 얻을 수 있는지 확인합니다. (여기서 *Query Queue*가 개입합니다.)
2. Processing (CPU-Slot 결합): 슬롯이 할당되면 CPU가 해당 슬롯의 태스크(Pipeline Driver)를 실행합니다.
3. Buffering (메모리 점유): 데이터를 읽어오면서 메모리에 해시 테이블을 빌드합니다. 이때 메모리가 부족하면 쿼리가 대기하거나(v2), 다른 쿼리의 메모리를 뺏으려다 실패하여 종료됩니다.
──────────
3. 구조적 요약표
항목 | 상관관계 요약 | 특징
CPU ↔️ Slot | 1:1 대응 (이상적) | 슬롯이 많을수록 CPU 사용률이 올라가며 처리 속도가 빨라짐.
Slot ↔️ 메모리 | 정비례 | 병렬 실행 단위(Slot)가 많아질수록 쿼리가 요구하는 총 메모리 양이 증가함.
CPU ↔️ 메모리 | 간접적 | CPU 연산 속도가 빨라 데이터 처리가 급증하면, 메모리 버퍼로 데이터가 몰려 순간 메모리 점유율(Peak)이 상승함.
──────────
4. 최적화를 위한 인사이트
1. 메모리가 자주 터진다면?
* pipeline_dop (슬롯 수)를 낮추어 병렬도를 줄이세요. 속도는 조금 느려지지만 메모리 점유율을 안정적으로 유지할 수 있습니다.
2. CPU 사용률은 낮은데 쿼리가 느리다면?
* 슬롯(병렬도)이 너무 낮게 설정되어 CPU 코어를 다 못 쓰고 있을 가능성이 큽니다.
3. v2 쿼리 큐의 역할:
* 위의 세 가지 요소(CPU, Slot, 메모리)의 균형이 깨지지 않도록, *메모리가 부족하거나 CPU가 너무 바쁘면 아예 새로운 "Slot"을 내어주지 않고 줄을 세우는 역할*을 합니다.
결론적으로, `query_queue_v2`는 특정 노드에 과도한 *Slot(병렬도)*이 할당되어 *메모리*가 고갈되는 것을 *CPU/메모리 상태 모니터링*을 통해 FE 단에서 차단하는 지능적인 제어 장치입니다.
References
• administration/management/resource_management/query_queues.md
• administration/management/resource_management/resource_group.md
• faq/resource_isolation_faq.md
• administration/management/monitor_manage_big_queries.md
• introduction/Architecture.md
• administration/management/monitoring/metrics.md
• sql-reference/System_variable.md
References
• administration/management/resource_management/query_queues.md
• administration/management/resource_management/resource_group.md
• faq/resource_isolation_faq.md
• administration/management/monitor_manage_big_queries.md
• introduction/Architecture.mdRocky
07/16/2026, 4:14 AMRocky
07/16/2026, 4:14 AMRocky
07/16/2026, 4:14 AMRocky
07/16/2026, 4:14 AMRocky
07/16/2026, 4:14 AMRonJay
07/16/2026, 5:01 AMRocky
07/16/2026, 5:01 AMpipeline_dop (Degree of Parallelism)는 StarRocks의 Pipeline 엔진이 *하나의 쿼리를 수행할 때 각 노드(BE/CN)에서 얼마나 많은 CPU 코어를 병렬로 사용할지*를 결정하는 핵심 변수입니다.
효율적인 튜닝을 위한 가이드를 정리해 드립니다.
──────────
1. 기본 원칙: 0 (Auto) 추천
StarRocks 3.x 버전부터는 `pipeline_dop`의 기본값이 *`0`*입니다.
* 작동 방식: 시스템이 노드의 물리적 CPU 코어 수를 자동으로 감지하여 최적의 병렬도를 계산합니다.
* 권장: 특별한 성능 병목이 없다면 기본값인 `0`을 사용하는 것이 가장 안전하고 효율적입니다.
──────────
2. 수동 설정 시 기준점 (CPU 코어 수 기반)
수동으로 튜닝해야 하는 상황(예: 특정 쿼리의 극단적 가속화 필요)이라면 다음 공식을 따릅니다.
* 최대 한계치: 해당 노드의 *물리적 CPU 코어 수*를 넘지 않도록 합니다.
* 예: 32코어 장비라면 `pipeline_dop`를 32 이하로 설정.
* 일반적인 최적치: 보통 코어 수의 1/2 정도가 가장 가성비가 좋습니다. (병렬도가 너무 높으면 CPU 캐시 효율이 떨어지고 컨텍스트 스위칭 비용이 증가하기 때문입니다.)
──────────
3. 상황별 튜닝 시나리오
A. 대규모 ETL 및 복잡한 배치 분석 (Low Concurrency, Big Query)
동시에 돌아가는 쿼리는 적은데, 하나의 쿼리가 아주 많은 데이터를 처리해야 할 때입니다.
* 설정: `pipeline_dop`를 물리 코어 수와 동일하게 설정 (예: 16코어면 16).
* 효과: 단일 쿼리가 모든 CPU 자원을 쏟아부어 실행 시간을 최소화합니다.
B. 고성능 서비스 및 동시 접속자가 많을 때 (High Concurrency, Small Query)
수십~수백 명의 사용자가 동시에 짧은 쿼리를 날릴 때입니다.
* 설정: `pipeline_dop`를 낮게 설정 (예: 2, 4 또는 8).
* 효과: 개별 쿼리가 사용하는 슬롯(코어) 수를 제한하여, 더 많은 사용자의 쿼리가 대기 없이 동시에 실행될 수 있도록 합니다.
──────────
4. `pipeline_dop`와 메모리의 상관관계 (주의사항)
가장 중요한 포인트입니다. `pipeline_dop`를 높이면 메모리 사용량도 선형적으로 증가합니다.
* 이유: 데이터를 처리하는 "작업대(Slot)"가 늘어날수록, 각 작업대가 데이터를 담아두는 버퍼 메모리 공간도 그만큼 더 필요하기 때문입니다.
* 증상: 만약 `pipeline_dop`를 높였는데 Memory limit exceeded 에러가 빈번해진다면, 병렬도를 다시 낮추어야 합니다.
──────────
5. 튜닝 방법 (SQL)
* 현재 세션에서만 테스트: (위험 부담이 적으므로 가장 먼저 시도)
sql
SET pipeline_dop = 16;
SELECT ... ;
* 시스템 전체 적용:
sql
SET GLOBAL pipeline_dop = 8;
* 특정 리소스 그룹에 적용 (추천): 특정 그룹의 사용자만 고성능을 쓰게 하고 싶을 때 유용합니다.
sql
ALTER RESOURCE GROUP 'high_priority_group' SET ('concurrency_limit' = '10');
-- 리소스 그룹 내에서 세션 변수로 조절 권장
──────────
6. 튜닝 결과 확인법 (Profile 분석)
쿼리 실행 후 `Get_Query_Profile`을 통해 다음 항목을 확인하세요.
* PipelineDop: 실제 적용된 병렬도.
* ActiveTime: CPU가 실제로 일한 시간.
* ScheduleTime: CPU를 기다린 시간 (이 시간이 너무 길면 `pipeline_dop`가 코어 수 대비 너무 높은 것임).
요약 가이드라인
1. *기본은 `0`*으로 두고 시스템에 맡긴다.
2. 단일 쿼리 속도가 너무 느려 가속하고 싶다면 코어 수의 50% ~ 100% 사이로 높여본다.
3. 동시 사용자가 많아 쿼리가 대기 상태에 자주 빠진다면 *코어 수의 25% 이하*로 낮춰서 자원을 쪼개 쓴다.
4. 메모리 부족 현상이 나타나면 무조건 `pipeline_dop`를 낮춘다.
References
• sql-reference/System_variable.md
• administration/execution_engine/Pipeline_engine.md
• administration/management/resource_management/resource_group.md
• administration/management/monitor_manage_big_queries.mdRonJay
07/16/2026, 5:13 AMRocky
07/16/2026, 5:13 AMSHOW RUNNING QUERIES 명령에서 확인하신 *Slot 1, Fragment 1, DOP 0*은 해당 쿼리가 현재 어떤 리소스 설정으로 대기 중이거나 실행 중인지를 나타내는 지표입니다.
각 항목의 의미는 다음과 같습니다.
1. Slots: 1
* 의미: 이 쿼리가 쿼리 큐(Query Queue)에서 차지하고 있는 *논리적인 점유 단위*입니다.
* 현재 상태: StarRocks의 현재 구현상, 모든 쿼리는 기본적으로 *`1`*개의 슬롯을 차지하도록 고정되어 있습니다. 즉, 리소스 그룹 등에 설정된 최대 동시 실행 수(Concurrency Limit) 중 1칸을 사용하고 있다는 뜻입니다.
2. Fragments: 1
* 의미: 실행 계획(Query Plan)이 몇 개의 *단위(Fragment)*로 쪼개졌는지를 나타냅니다.
* 분석: `1`이라는 숫자는 쿼리 구조가 매우 단순하다는 뜻입니다.
* 보통 여러 노드에서 데이터를 읽고 조인(Join)하거나 대량의 데이터를 교환(Shuffle)해야 하는 복잡한 쿼리는 Fragment 수가 수십 개가 넘기도 합니다.
* `1`인 경우는 단순한 SELECT 1, SHOW 명령어, 혹은 아주 간단한 메타데이터 조회일 가능성이 높습니다.
3. DOP: 0
* 의미: Degree of Parallelism, 즉 병렬 처리 수준 설정값입니다.
* 분석: 여기서 `0`은 병렬도가 없다는 뜻이 아니라, "Auto-DOP" (자동 설정) 모드를 의미합니다.
* StarRocks는 pipeline_dop 변수가 `0`일 때, 시스템의 CPU 코어 수와 쿼리의 복잡도를 계산하여 최적의 병렬도를 자동으로 결정합니다.
* 사용자가 강제로 `SET pipeline_dop = 8;`과 같이 설정했다면 해당 숫자가 표시되지만, 기본 설정 상태에서는 `0`으로 표시됩니다.
──────────
요약하자면
*"이 쿼리는 매우 단순한 구조(Fragment 1)를 가지고 있으며, 시스템이 자동으로 병렬도를 결정(DOP 0)하여 실행 중이고, 쿼리 큐에서 1개의 실행권(Slot 1)을 얻어서 돌아가고 있다"*고 해석하시면 됩니다.
성능상 문제가 있는 상황이 아니라면, 지극히 정상적이고 효율적으로 관리되고 있는 상태입니다.
References
• using_starrocks/running_queries.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_RUNNING_QUERIES.md
• administration/execution_engine/Pipeline_engine.md
• sql-reference/System_variable.md
References
• using_starrocks/running_queries.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_RUNNING_QUERIES.md
• administration/execution_engine/Pipeline_engine.md
• sql-reference/System_variable.md
• administration/management/resource_management/query_queues.md
• administration/Query_planning.md
References
• using_starrocks/running_queries.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_RUNNING_QUERIES.md
• sql-reference/sql-statements/loading_unloading/SHOW_LOAD.mdRonJay
07/16/2026, 5:31 AMRocky
07/16/2026, 5:31 AMquery_queue_mem_used_pct_limit = 0.6 (BE 메모리 사용량이 60%를 넘으면 새 쿼리를 큐에 대기시킴)
* 에러 로그 상황:
* Used: 50,858,106,936 (약 50.8GB)
* Limit: 55,667,761,561 (약 55.6GB)
* 계산: 50.8 / 55.6 = 약 91.3% 사용 중
* 결과: BE의 물리적 메모리 한계(보통 mem_limit 기본값인 90%)를 초과하여 쿼리가 강제 종료(CANCELLED)되었습니다.
2. 왜 60% 제한이 작동하지 않았나요?
`query_queue_mem_used_pct_limit`는 신규 쿼리가 들어올 때 FE(Frontend)에서 "지금 실행해도 될까?"를 판단하는 문지기 역할을 합니다.
1. 쿼리 시작 후 메모리 팽창: 쿼리가 처음 시작될 때는 BE 메모리 사용량이 60% 미만이었으므로 FE는 실행을 허락했습니다. 하지만 실행 도중 조인(Join)이나 집계(Aggregation) 과정에서 데이터가 급격히 늘어나 실제 사용량이 91%까지 치솟은 것입니다.
2. 비쿼리 메모리 사용: 백그라운드에서 진행되는 컴팩션(Compaction), 캐시(Metadata Cache), 혹은 데이터 로딩(Load) 작업이 쿼리 실행 중에 메모리를 점유하여 전체 사용량을 끌어올렸을 수 있습니다.
3. 병렬 실행의 영향: 여러 쿼리가 동시에 60% 직전 상태에서 시작되었고, 이들이 동시에 실행되면서 합산 메모리가 한계를 넘었을 가능성이 큽니다.
3. 해결 방안
① 큐 제한 수치 하향 조정
쿼리 실행 중 메모리 증가폭이 크다면, 60%도 너무 높은 기준일 수 있습니다. 여유 공간(Buffer)을 더 확보하기 위해 수치를 낮추십시오.
sql
SET GLOBAL query_queue_mem_used_pct_limit = 0.4; -- 40%로 낮춤
② 개별 쿼리 메모리 제한 (exec_mem_limit)
하나의 쿼리가 전체 BE 메모리를 다 써버리지 않도록 세션 또는 전역 변수로 제한을 겁니다.
sql
SET GLOBAL exec_mem_limit = 17179869184; -- 예: 쿼리당 16GB 제한
③ BE 메모리 한계값 확인 (be.conf)
BE의 전체 메모리 한계가 너무 낮게 잡혀있지 않은지 확인하십시오.
* be.conf 파일의 mem_limit 설정 (기본값 90%).
* 만약 서버에 다른 프로세스가 없다면 물리 메모리 용량에 맞춰 적절히 설정되어 있는지 확인이 필요합니다.
④ 메모리 트래커 확인
어떤 부분이 메모리를 많이 쓰는지 상세히 보려면 BE의 웹 인터페이스를 통해 확인하십시오.
* http://<BE_IP>:<BE_HTTP_PORT>/mem_tracker
요약하자면: 현재 설정한 60% 제한은 *"입구 컷"*은 잘 하고 있지만, 이미 들어온 쿼리가 실행 중에 몸집을 너무 키워서 *"전체 용량(90%)"*을 터뜨리고 있는 상황입니다. 큐 제한을 더 엄격히 하거나(40~50%), 개별 쿼리의 최대 사용량을 제한하는 것이 해결책입니다.
References
• sql-reference/System_variable.md
• administration/management/BE_configuration.md
• faq/Sql_faq.md
• administration/management/resource_management/query_queues.md
References
• administration/management/BE_configuration.md
• knowledge/usage/best-practice.md
• faq/Sql_faq.md
• faq/operation_maintenance_faq.mdRonJay
07/16/2026, 5:37 AMRocky
07/16/2026, 5:37 AMGROUP BY 연산을 위해 데이터를 그룹화하고 합계를 계산하는 과정
* Sort: `ORDER BY`를 수행하기 위해 데이터를 정렬할 때 사용하는 버퍼
* Exchange: 노드 간에 데이터를 주고받기(Shuffle) 위해 잠시 담아두는 송수신 버퍼
2. 스토리지 레이어 (Storage Layer)
데이터를 디스크에서 읽어올 때 사용하는 메모리입니다.
* Scan: 디스크에서 데이터를 읽어와서 Chunk 단위로 만드는 과정
* Column Reader: 특정 컬럼 데이터를 읽고 해석(Decoding)하는 과정
* Filter: WHERE 조건에 맞는 데이터를 걸러내는 작업
3. 왜 중요한가요? (사용자 질문과의 연관성)
질문하신 query_queue_mem_used_pct_limit 설정이 바로 이 *`query_pool`의 크기를 감시*하는 설정입니다.
* 동작 방식: 새로운 쿼리가 들어올 때, StarRocks는 "지금 `query_pool`이 BE 전체 메모리의 몇 %를 쓰고 있지?"를 체크합니다.
* 한계 도달: 만약 `query_pool`의 점유율이 설정하신 `0.6`(60%)을 넘었다면, 새로운 쿼리는 실행되지 못하고 큐(Queue)에서 대기하게 됩니다.
* 에러 발생 원인: 이전 질문에서 발생한 에러는, 이미 실행 허락을 받은 쿼리들이 query_pool 안에서 (Join이나 Aggregation 등을 하느라) 몸집을 불리다가 BE 전체 한계치(보통 90%)를 뚫어버렸기 때문입니다.
요약
`query_pool`은 *"데이터를 읽고(Scan), 묶고(Group By), 합치고(Join) 하는 모든 분석 활동"*에 쓰이는 실질적인 작업 공간입니다.
실시간 사용량이 궁금하시다면 BE 서버의 http://<BE_IP>:<BE_HTTP_PORT>/mem_tracker?type=query_pool 주소에 접속하여 어떤 쿼리가 이 풀을 가장 많이 차지하고 있는지 상세히 확인할 수 있습니다.
References
• administration/management/resource_management/Memory_management.md
• administration/management/resource_management/query_queues.md
• faq/Sql_faq.md
References
• administration/management/resource_management/Memory_management.md
• administration/management/monitoring/metrics.md
• administration/management/resource_management/query_queues.mdRonJay
07/16/2026, 5:41 AMRocky
07/16/2026, 5:41 AMSET GLOBAL 명령을 사용하면 즉시 반영됩니다. 상세 내용은 다음과 같습니다.
1. 즉시 반영 (No Restart)
* SET GLOBAL 명령은 실행 즉시 FE(Frontend) 메모리에 반영되며, 설정값은 StarRocks 내부 메타데이터에 저장됩니다. 따라서 클러스터를 껐다 켜지 않아도 됩니다.
2. 적용 범위 주의사항
* 새로운 세션: `SET GLOBAL`로 설정한 후 *새롭게 맺어지는 연결(Session)*부터 변경된 타임아웃 값이 적용됩니다.
* 기존 세션: 이미 연결되어 있는 세션은 이전 타임아웃 값을 그대로 유지합니다. 기존 세션에도 바로 적용하고 싶다면 해당 세션에서 SET query_timeout = ...; (Global 없이) 명령을 직접 실행하거나, 클라이언트를 재접속해야 합니다.
3. 참고 (v3.4.0 이상 사용 시)
v3.4.0 버전부터는 타임아웃 변수가 용도에 따라 분리되었습니다.
* query_timeout: 순수 조회(SELECT) 쿼리에만 적용됩니다.
* insert_timeout: INSERT, UPDATE, DELETE, CTAS, 구체화된 뷰(MV) 새로고침 등 데이터를 변경하는 작업에는 이 변수가 사용되므로, 목적에 맞게 두 변수를 모두 확인하시는 것이 좋습니다.
설정 예시:
sql
-- 전역 설정 (재기동 불필요, 새 연결부터 적용)
SET GLOBAL query_timeout = 600;
-- 현재 연결된 세션만 즉시 변경
SET query_timeout = 600;
References
• sql-reference/System_variable.md
• faq/operation_maintenance_faq.md
• administration/management/FE_configuration.md
References
• sql-reference/System_variable.md
• faq/operation_maintenance_faq.md
• administration/management/resource_management/query_queues.md
• administration/management/FE_configuration.mdRonJay
07/16/2026, 6:07 AMRocky
07/16/2026, 6:07 AMquery_queue_concurrency_limit)
가장 먼저 확인해야 할 전역 변수입니다. 이 값이 10으로 설정되어 있으면 BE 노드당 실행되는 쿼리 수가 10개로 제한됩니다.
* 확인 방법: SHOW VARIABLES LIKE 'query_queue_concurrency_limit';
* 해결 방법: 값을 늘리거나 제한을 없애려면 0으로 설정합니다.
sql
SET GLOBAL query_queue_concurrency_limit = 20; -- 20개로 상향
-- 또는
SET GLOBAL query_queue_concurrency_limit = 0; -- 무제한 (비권장, 메모리 에러 위험)
2. 리소스 그룹(Resource Group)의 concurrency_limit
만약 리소스 그룹을 사용 중이라면, 해당 그룹에 설정된 동시성 제한이 10일 수 있습니다. StarRocks는 리소스 그룹별로 쿼리 슬롯을 할당하여 자원을 격리합니다.
* 확인 방법: SHOW RESOURCE GROUPS; 명령어로 concurrency_limit 컬럼 값을 확인하세요.
* 해결 방법: 리소스 그룹 설정을 변경합니다.
sql
ALTER RESOURCE GROUP 그룹이름 WITH ('concurrency_limit' = '20');
3. 최신 버전(v3.3.4+)의 Query Queue v2 설정
최근 버전에서는 FE 설정인 `query_queue_v2_concurrency_level`을 통해 전체 시스템 슬롯을 계산합니다.
* 계산식: 슬롯 수 = Level(기본4) _ BE 노드 수 _ BE 코어 수
* 만약 소규모 테스트 환경(1개 BE, 적은 코어 수)이라면 기본 계산 결과가 10 내외로 잡힐 수 있습니다. 이 경우 FE 설정(fe.conf)이나 시스템 변수를 조정해야 합니다.
왜 10개로 제한되나요?
동시성을 제한하는 이유는 시스템 안정성 때문입니다.
* 동시에 너무 많은 쿼리가 "Slot"을 차지하고 실행되면, 앞서 경험하신 것처럼 *BE 메모리 부족(OOM)*으로 인해 모든 쿼리가 한꺼번에 취소될 수 있습니다.
* 따라서 10개로 고정되어 나머지가 대기(Pending) 중이라면, 현재 설정된 동시성 제한이 시스템을 보호하고 있는 상태입니다.
권장 조치:
현재 BE의 CPU 및 메모리 사용률에 여유가 있다면 query_queue_concurrency_limit 또는 리소스 그룹의 `concurrency_limit`을 단계적으로 높여보시기 바랍니다.
References
• sql-reference/System_variable.md
• administration/management/resource_management/query_queues.md
• administration/management/resource_management/resource_group.md
• faq/resource_isolation_faq.md
References
• sql-reference/System_variable.md
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• administration/management/resource_management/resource_group.md
-group)
• administration/management/FE_configuration.md
• administration/management/monitoring/metrics.md
References
• sql-reference/System_variable.md
• administration/management/resource_management/query_queues.md
• administration/management/FE_configuration.mdRonJay
07/16/2026, 6:17 AMRocky
07/16/2026, 6:18 AMSHOW BACKENDS 명령어나 모니터링 대시보드에서 *`MemUsedPct`*(또는 MemUsePct)가 *0%*로 표시된다면, 시스템이 자원 사용량을 수집하거나 보고하는 기능이 활성화되지 않았을 가능성이 큽니다.
이를 해결하기 위해 다음 사항들을 확인하고 설정해 보세요.
1. 자원 격리 기능 활성화 (enable_resource_group)
StarRocks에서 BE(Backend)의 상세 CPU 및 메모리 사용률을 FE(Frontend)로 보고하고 관리하려면 자원 격리(Resource Group) 기능이 켜져 있어야 합니다. v3.x 버전부터는 기본값이 `true`인 경우가 많지만, 만약 `false`로 되어 있다면 자원 사용량 통계가 집계되지 않습니다.
* 확인 방법:
sql
SHOW VARIABLES LIKE 'enable_resource_group';
* 설정 방법:
sql
SET GLOBAL enable_resource_group = true;
2. BE의 자원 보고 주기 확인 (report_resource_usage_interval_ms)
BE는 일정 주기마다 자신의 자원 사용량(CPU, Mem)을 FE에게 보고합니다. 이 주기가 너무 길거나 설정에 문제가 있으면 0으로 보일 수 있습니다. (기본값은 1000ms, 즉 1초입니다.)
* 확인/설정: 이 값은 FE의 `fe.conf`에서 관리하거나 시스템 변수로 확인 가능합니다. 일반적으로는 따로 건드리지 않아도 되지만, `enable_resource_group`이 켜져 있는데도 0%라면 확인이 필요합니다.
3. BE 메모리 제한(mem_limit) 설정 여부
`MemUsedPct`는 *"현재 사용 메모리 / 전체 메모리 제한(mem_limit)"*의 비율입니다. 만약 BE 설정(be.conf)에서 `mem_limit`이 비정상적이거나 시스템 메모리를 제대로 인식하지 못하는 환경(예: 일부 컨테이너 환경)이라면 계산 결과가 0%로 나올 수 있습니다.
* `be.conf`에 `mem_limit`이 적절히 설정되어 있는지(예: mem_limit = 80%) 확인해 보세요.
4. 쿼리 큐 v2 관련 (v3.3 이상)
만약 *Query Queue v2*를 사용 중이라면, 자원 사용량 기반의 큐 동작을 위해 아래 변수도 체크해야 합니다.
sql
-- 쿼리 큐 기능 자체가 활성화되어 있는지 확인
SHOW VARIABLES LIKE 'query_queue_v2_enabled';
요약: 당장 해볼 수 있는 조치
대부분의 경우 SET GLOBAL enable_resource_group = true; 명령어로 해결됩니다. 이 설정을 적용한 후 1~2분 정도 기다렸다가 다시 `SHOW BACKENDS`를 확인해 보세요.
만약 여전히 0%라면, 현재 사용 중인 StarRocks의 버전과 어떤 화면(예: SHOW BACKENDS, Grafana 대시보드 등)에서 0%로 보이는지 알려주시면 더 정확한 답변이 가능합니다.
References
• sql-reference/sql-statements/cluster-management/resource_group/SHOW_USAGE_RESOURCE_GROUPS.md
• administration/management/resource_management/resource_group.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_BACKENDS.md
• administration/management/resource_management/query_queues.md
References
• administration/management/resource_management/resource_group.md
• sql-reference/sql-statements/cluster-management/resource_group/SHOW_USAGE_RESOURCE_GROUPS.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_BACKENDS.md
• administration/management/resource_management/query_queues.md
• administration/management/monitoring/metrics.md
References
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_BACKENDS.md
• faq/operation_maintenance_faq.md
• sql-reference/sql-statements/cluster-management/resource_group/SHOW_USAGE_RESOURCE_GROUPS.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_PROC.mdRonJay
09/02/2026, 2:10 AMRocky
09/02/2026, 2:10 AM_statistics_)에 정보가 없는 5개 컬럼에 대해서는 *Iceberg 고유의 메타데이터(Manifest files)*를 직접 참조합니다.
* 파일 단위 정보: Iceberg Manifest 파일에는 컬럼별 `min`/`max`, null_count, row_count 등이 저장되어 있습니다.
* 동작: StarRocks는 수집된 통계가 없더라도 Iceberg가 제공하는 이 파일 레벨의 통계 정보를 읽어와 필터링 성능(Data Skipping) 및 조인 비용 계산에 활용합니다.
2. 기본 휴리스틱(Heuristics) 적용
만약 Iceberg Manifest에도 정보가 없거나, `NDV`(Distinct Value 개수)와 같이 정밀한 정보가 필요한 경우 StarRocks는 미리 정의된 *기본값(Default values)*을 사용합니다.
* NDV 추정: 해당 컬럼의 고유 값 개수를 전체 행 수의 일정 비율로 가정하거나 고정된 상수를 사용합니다.
* 선택도(Selectivity): = 조건은 매우 높은 선택도로, range 조건은 1/3 등으로 가정하는 방식입니다.
* 결과: 이 경우 통계가 있는 5개 컬럼보다는 실행 계획의 최적화 수준이 낮아질 수 있습니다.
3. Query-triggered ANALYZE (v3.4.0 이상)
StarRocks v3.4.0 이상 버전을 사용 중이라면, 쿼리 실행 시 통계가 부족한 컬럼을 감지하여 *자동으로 백그라운드 수집 작업*을 시작합니다.
* 동작 방식: 현재 쿼리는 일단 1, 2번의 방식으로 실행되지만, 시스템은 내부적으로 "이 5개 컬럼에 대한 통계가 필요하다"고 판단하여 백그라운드에서 ANALYZE 작업을 생성합니다.
* 효과: 이 작업이 완료된 후, 다음에 같은 테이블에 쿼리를 던지면 10개 컬럼 모두에 대해 정확한 통계를 바탕으로 최적의 실행 계획을 생성합니다.
4. 요약 및 권장사항
구분 | 통계가 있는 5개 컬럼 | 통계가 없는 5개 컬럼
참조 데이터 | StarRocks 내부 통계 DB (NDV, Histogram 등 상세 정보) | Iceberg Manifest (`min`/`max` 등) + 기본 휴리스틱
최적화 수준 | 매우 높음 (정확한 비용 계산) | 보통 (Manifest 기반 데이터 스킵은 가능)
자동 보정 | - | v3.4+ 에서 쿼리 후 백그라운드 수집 발생
Tip: 만약 해당 쿼리가 비즈니스적으로 매우 중요하고 성능 민감도가 높다면, 시스템이 자동으로 수집하기를 기다리기보다 아래 명령어로 전체 컬럼에 대한 통계를 수집하는 것이 좋습니다.
sql
-- 10개 컬럼 전체 또는 테이블 전체에 대해 수집
ANALYZE TABLE iceberg_catalog.db_name.table_name;
References
• using_starrocks/Cost_based_optimizer.md
• data_source/feature-support-data-lake-analytics.md
• sql-reference/sql-statements/data-manipulation/ANALYZE_TABLE.md
References
• using_starrocks/Cost_based_optimizer.mdRonJay
09/02/2026, 2:20 AMRocky
09/02/2026, 2:24 AMWHERE date = '2023-10-01')이 있다면, StarRocks는 Iceberg의 스냅샷 정보를 보고 해당 파티션에 속하지 않는 모든 디렉토리/파일을 계획(Planning) 단계에서 즉시 제외합니다.
2. File-level Skipping (파일 단위 건너뛰기)
Iceberg의 *Manifest 파일*에는 각 데이터 파일의 컬럼별 `min`/`max` 값이 기록되어 있습니다.
* 동작: 쿼리 조건이 `age > 30`인데, 어떤 파일의 age 컬럼 max 값이 25라면 StarRocks는 이 *파일 전체를 읽지 않고 스킵*합니다.
* 통계의 역할: 말씀하신 '5개 컬럼에 대한 통계'가 Iceberg 자체 메타데이터에 있는 min/max를 의미한다면, 이 정보를 활용해 파일을 골라냅니다.
3. "planfile" (Planning) 단계의 동작
사용자께서 언급하신 "planfile"은 아마도 쿼리 계획(Planning) 단계를 말씀하시는 것 같습니다.
* 작은 테이블: FE(Frontend)가 혼자서 메타데이터(Manifest)를 읽어 스캔할 파일을 결정합니다.
* 대규모 테이블 (Distributed Plan): 메타데이터 파일이 너무 많으면(예: 파일이 수만 개 이상), FE가 직접 다 읽지 않고 *여러 BE(Backend) 노드에 Manifest 읽기 작업을 분산*시킵니다. 이를 통해 어떤 파일을 읽어야 할지 결정하는 '계획 단계' 자체를 가속화합니다. (이때도 실제 데이터 파일을 다 읽는 것이 아니라, 메타데이터 파일만 읽어서 스캔 대상을 정하는 것입니다.)
4. Row-level Skipping (파일 내부 건너뛰기)
파일을 읽기로 결정했더라도, 파일 형식이 Parquet나 ORC라면 파일 내부의 *Page/Offset 통계*를 보고 조건에 맞지 않는 데이터 블록은 건너뜁니다.
요약
* 통계가 있다면: 필요한 파일만 골라서 읽습니다. (전체 스캔 X)
* 통계가 부족하다면: (예: Manifest에 min/max가 없는 컬럼 조건 사용 시) 어쩔 수 없이 더 많은 파일을 열어봐야 하므로 성능이 떨어질 수 있습니다.
* Distributed Plan: 파일 목록을 뽑는 과정(Planning)조차 BE를 써서 빠르게 처리하므로, 파일이 아주 많아도 효율적으로 동작합니다.
따라서 10개 컬럼 중 통계가 있는 5개 컬럼을 조건절(WHERE)에 활용하신다면, 훨씬 더 공격적인 데이터 스킵이 일어나 쿼리 속도가 빨라집니다.
References
• data_source/catalog/iceberg/iceberg_catalog.md
• using_starrocks/Cost_based_optimizer.md
• data_source/feature-support-data-lake-analytics.md
References
• data_source/catalog/iceberg/iceberg_catalog.md
• using_starrocks/Cost_based_optimizer.md
• data_source/feature-support-data-lake-analytics.md
• sql-reference/sql-statements/data-manipulation/ANALYZE_TABLE.md
• administration/management/resource_management/resource_group.md
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.md
• administration/management/FE_configuration.md
• administration/management/monitoring/metrics.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_BACKENDS.md
• faq/operation_maintenance_faq.md
• sql-reference/sql-statements/cluster-management/resource_group/SHOW_USAGE_RESOURCE_GROUPS.md
• sql-reference/sql-statements/cluster-management/nodes_processes/SHOW_PROC.md
• data_source/datalake_faq.mdRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AMRocky
09/02/2026, 2:24 AM