Sangwon
09/07/2026, 12:16 AMRocky
09/07/2026, 12:16 AMDISTRIBUTED BY ... BUCKETS 숫자를 조금 줄여서 관리 효율을 더 높일 수 있습니다.
관련 상세 내용은 StarRocks 데이터 분포 가이드에서 확인하실 수 있습니다.
References
• faq/Deploy_faq.md
• deployment/plan_cluster.md
• faq/Others.md
• knowledge/usage/best-practice.mdSangwon
09/07/2026, 5:58 AMRocky
09/07/2026, 5:58 AMDELETE 작업을 직접 수행하기 어렵거나 효율이 떨어집니다.
2. Primary Key (기본 키)
* 특징: 키 값의 *유일성(Unique)*을 보장합니다. 동일한 키 값을 가진 데이터가 들어오면 기존 데이터를 새로운 데이터로 교체(Upsert)합니다.
* 동작 방식: 내부적으로 Delete+Insert 전략을 사용합니다. 데이터를 읽을 때 중복을 제거하는 방식이 아니라, 쓸 때 미리 위치를 찾아 삭제 표시를 하므로 쿼리 성능이 매우 빠릅니다 (Unique Key 모델보다 3~10배 빠름).
* 용도: MySQL 등 RDBMS에서 데이터를 실시간으로 동기화(CDC)하거나, 자주 업데이트/삭제가 발생하는 비즈니스 데이터 분석에 최적입니다.
* 제약: 파티션 컬럼과 버킷 컬럼이 반드시 Primary Key에 포함되어야 합니다.
──────────
요약 비교
구분 | Duplicate Key (기본값) | Primary Key
중복 허용 | 허용 (모든 데이터 보존) | 불허 (동일 키는 업데이트됨)
주요 동작 | Append-only (추가만 가능) | Upsert (업데이트/삭제 지원)
쓰기 성능 | 매우 높음 | 보통 (인덱스 업데이트 부하 존재)
읽기 성능 | 높음 | 매우 높음 (필터링 효율 극대화)
권장 시나리오 | 로그, 이벤트 데이터 적재 | 실시간 변경 데이터 (CDC), 마스터 데이터
팁: 만약 단순히 데이터를 쌓아두고 대규모 분석만 한다면 *Duplicate Key*를, 실시간으로 변하는 데이터를 관리하고 빠른 조회 성능이 필요하다면 *Primary Key*를 선택하는 것이 좋습니다.
References
• table_design/table_types/duplicate_key_table.md
• table_design/table_types/primary_key_table.md
• table_design/table_types/table_capabilities.md
References
• table_design/table_types/primary_key_table.md
• table_design/table_types/table_capabilities.md
• table_design/table_types/duplicate_key_table.mdSangwon
09/07/2026, 6:04 AMRocky
09/07/2026, 6:04 AMDUPLICATE KEY 테이블에서 *Key 컬럼*과 *일반 컬럼(Value 컬럼)*의 가장 큰 차이점은 *"데이터가 정렬되어 저장되는가"*입니다.
StarRocks의 Duplicate Key 모델에서는 키로 지정된 컬럼들을 기준으로 데이터를 물리적으로 *정렬(Sort)*하여 저장합니다.
1. Key 컬럼 (정렬 키)
* 물리적 정렬: `DUPLICATE KEY(col1, col2)`라고 지정하면, 디스크에 저장될 때 col1 순으로, 그 다음 col2 순으로 데이터가 정렬되어 쌓입니다.
* 인덱스 역할: 데이터가 정렬되어 있으므로, `WHERE col1 = 10`과 같은 쿼리를 실행할 때 StarRocks는 모든 데이터를 뒤지지 않고 *바이너리 서치(Binary Search)*처럼 빠르게 해당 데이터를 찾아낼 수 있습니다. (이것을 'Short-key Index'라고 부릅니다.)
* 필터링 성능: Key 컬럼을 조건절(WHERE)에 사용하면 일반 컬럼을 사용할 때보다 조회가 압도적으로 빠릅니다.
2. 일반 컬럼 (Non-key / Value 컬럼)
* 비정렬 저장: Key 컬럼 뒤에 따라오는 나머지 데이터들입니다. 정렬되지 않은 상태로 저장됩니다.
* 단순 보관: 데이터를 조회할 때(SELECT) 값을 보여주는 용도이지, 데이터를 찾는(Search) 용도로는 효율이 낮습니다.
* 조회 성능: 일반 컬럼을 WHERE 조건에 넣으면, StarRocks는 정렬 인덱스를 타지 못하고 전체 데이터를 스캔(Full Scan)해야 할 수도 있습니다. (물론 Zone Map 인덱스나 별도의 Bitmap 인덱스가 있다면 보완되지만, 기본적으로 Key 컬럼보다 느립니다.)
──────────
요약 비교
구분 | Key 컬럼 (DUPLICATE KEY 내 정의) | 일반 컬럼 (나머지)
정렬 여부 | 항상 정렬됨 | 정렬되지 않음
조회 효율 | 매우 빠름 (정렬 인덱스 활용) | 상대적으로 느림 (풀 스캔 가능성)
컬럼 순서 | 중요함 (왼쪽 컬럼부터 정렬 기준이 됨) | 순서가 성능에 미치는 영향 적음
권장 대상 | `WHERE`나 JOIN 조건에 자주 쓰이는 컬럼 | 단순히 결과값으로 보여주는 컬럼
주의할 점: 컬럼 순서
`DUPLICATE KEY(A, B)`로 지정하면 A에 대해서는 매우 빠르지만, B에 대해서는 A만큼 빠르지 않을 수 있습니다. 따라서 *가장 자주 필터링 조건으로 사용되는 컬럼을 맨 앞(가장 왼쪽)*에 배치하는 것이 테이블 설계의 핵심입니다.
References
• table_design/table_types/duplicate_key_table.md
• table_design/Data_distribution.md
• table_design/Sort_key.md
• table_design/table_types/table_capabilities.md
References
• table_design/table_types/duplicate_key_table.md
• table_design/table_types/primary_key_table.md
• table_design/table_types/table_capabilities.md
• table_design/sort_key.mdSangwon
09/07/2026, 6:05 AMSangwon
09/07/2026, 6:05 AMRocky
09/07/2026, 6:06 AMUPDATE 명령어를 공식적으로 지원하지 않거나, 매우 제한적입니다.
* 중복 허용: 동일한 ID를 가진 데이터를 다시 넣으면 기존 데이터가 바뀌는 게 아니라, 똑같은 데이터가 한 줄 더 생깁니다. 결국 읽을 때 어떤 데이터가 최신인지 알 수 없게 됩니다.
* 삭제의 어려움: 특정 조건의 데이터를 삭제하는 `DELETE`는 가능하지만, 대량의 데이터를 수시로 삭제하기에는 성능 최적화가 되어 있지 않습니다.
2. 해결책: Primary Key 테이블 사용
데이터가 계속 바뀌는 상황(Upsert, CDC 등)이라면 반드시 *Primary Key 테이블*을 사용해야 합니다.
* 실시간 업데이트(Upsert): 동일한 키(PK)로 데이터가 들어오면 기존 데이터를 자동으로 찾아 최신값으로 업데이트합니다.
* 강력한 삭제 기능: 특정 행을 삭제하거나, 조건에 맞는 데이터를 지우는 작업이 매우 빠릅니다.
* 압도적인 쿼리 성능: Primary Key 테이블은 'Delete+Insert' 전략과 전용 인덱스를 사용하기 때문에, 업데이트가 잦은 환경에서도 Duplicate Key나 Unique Key 모델보다 *3~10배 더 빠른 조회 성능*을 보여줍니다.
결론
* 로그, 센서 데이터처럼 쌓기만 한다면? → Duplicate Key
* 사용자 정보, 주문 상태처럼 값이 계속 바뀐다면? → Primary Key
지금 고민 중이신 상황은 전형적인 *Primary Key 테이블*이 필요한 케이스입니다. 테이블 생성 시 `PRIMARY KEY(컬럼명)`를 정의하여 사용하시길 권장합니다.
References
• table_design/table_types/primary_key_table.md
• table_design/table_types/table_capabilities.md
• table_design/table_types/duplicate_key_table.md
• best_practices/primarykey_table.md
• table_design/table_types/primary_key_table.md
• table_design/table_types/table_capabilities.md
• table_design/table_types/duplicate_key_table.md
• best_practices/primarykey_table.md
References
• table_design/table_types/primary_key_table.md
• best_practices/primarykey_table.md
• table_design/table_types/table_capabilities.mdSangwon
09/07/2026, 6:18 AMRocky
09/07/2026, 6:21 AMDISTRIBUTED BY HASH 컬럼을 선정할 때는 다음 3가지 원칙을 기억하시면 됩니다.
1. 기술적 제약 사항 (필수)
Primary Key 테이블에서는 *`DISTRIBUTED BY HASH`에 사용되는 컬럼이 반드시 PRIMARY KEY 컬럼의 일부(Subset)*여야 합니다.
* 예: PK가 `(user_id, order_id)`라면, 분포 키는 `user_id`나 order_id 또는 둘 다 포함할 수 있지만, PK에 없는 event_time 같은 컬럼은 쓸 수 없습니다.
2. 이상적인 컬럼 선정 기준
가장 좋은 컬럼은 *"데이터가 골고루 퍼지면서도, 조회할 때 자주 쓰이는 컬럼"*입니다.
* 높은 카디널리티(High Cardinality): 중복된 값이 적고 고유한 값이 많은 컬럼이 좋습니다. (예: user_id, order_id, device_id)
* 값이 몇 개 없는 컬럼(예: gender, status)을 쓰면 특정 버킷에만 데이터가 몰려 성능이 떨어집니다(Data Skew).
* 조회 조건(WHERE)에 자주 등장하는 컬럼: 특정 ID로 필터링을 자주 한다면, 그 컬럼을 분포 키로 잡으세요. StarRocks가 해당 데이터가 들어있는 버킷만 콕 집어서 읽는 *Bucket Pruning*이 작동해 성능이 비약적으로 향상됩니다.
* 조인(Join)에 자주 쓰이는 컬럼: 두 테이블을 조인할 때 분포 키를 맞추면 네트워크를 통한 데이터 전송 없이 로컬에서 바로 조인하는 *Colocate Join*이 가능해져 매우 빠릅니다.
3. 실전 팁
* 컬럼 개수: 보통 *1~2개*의 컬럼만 지정하는 것이 권장됩니다. 너무 많은 컬럼을 묶으면 오히려 조건절을 통한 버킷 최적화(Pruning)가 어려워질 수 있습니다.
* 데이터 불균형 확인: 만약 특정 ID에 데이터가 너무 몰려 있다면(예: '비회원' ID 하나에 로그가 90% 집중됨), 해당 ID를 분포 키로 쓰면 특정 서버만 과부하가 걸립니다. 이럴 땐 두 개의 컬럼을 조합하여 분포 키로 지정하는 것이 좋습니다.
추천 예시:
sql
CREATE TABLE orders (
order_id BIGINT NOT NULL,
user_id INT NOT NULL,
...
)
PRIMARY KEY (order_id)
-- order_id는 유니크하므로 데이터가 가장 고르게 분산됩니다.
DISTRIBUTED BY HASH(order_id);
References
• table_design/table_types/primary_key_table.md
• table_design/data_distribution/Data_distribution.md
• best_practices/bucketing.md
• table_design/table_types/primary_key_table.md
• table_design/data_distribution/Data_distribution.md
• best_practices/bucketing.md
References
• table_design/table_types/primary_key_table.md
• table_design/data_distribution/Data_distribution.md
• best_practices/bucketing.md
• best_practices/primarykey_table.md
• table_design/table_types/table_capabilities.md
• table_design/table_types/table_capabilities.md
• table_design/table_types/primary_key_table.md
• table_design/data_distribution/Data_distribution.md
• best_practices/bucketing.md
• best_practices/primarykey_table.md
• table_design/table_types/table_capabilities.md
• table_design/table_types/primary_key_table.md
• table_design/data_distribution/Data_distribution.md
• best_practices/bucketing.md
• best_practices/primarykey_table.md
• table_design/table_types/table_capabilities.mdRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AMRocky
09/07/2026, 6:21 AM