<@U0A71G31CDV> Minio에 parquet파일 올려둔다음, insert into...
# questions-and-troubleshooting
s
@Rocky Minio에 parquet파일 올려둔다음, insert into select * from FILES 로 넣으려고하는데, iceberg라서 spark connector로 merge into 구문을 쓰고싶어, 그안에 source부분에 select * from FILES구문이 들어가도되나
r
StarRocks의
FILES()
테이블 함수와 Spark의
MERGE INTO
구문을 혼합해서 사용하려는 시도로 보입니다. 결론부터 말씀드리면, 두 가지 이유로 해당 방식은 현재 불가능합니다. 1.
FILES()
함수는 StarRocks 전용입니다
`FILES()`는 StarRocks 엔진이 클라우드 스토리지(MinIO, S3 등)의 파일을 직접 읽고 스키마를 추론하기 위해 제공하는 *StarRocks 전용 SQL 확장*입니다. * Spark 환경(Spark Iceberg Connector 사용 시)에서는 StarRocks의
FILES()
함수를 인식할 수 없습니다. _ Spark에서 Parquet 파일을 읽으려면 Spark의 기본 기능을 사용해야 합니다:
spark.read.parquet("s3a://...")
또는 SQL에서
SELECT _ FROM parquet.path
. 2. StarRocks는 Iceberg 테이블에 대한 `MERGE INTO`를 아직 지원하지 않습니다 StarRocks는 현재(v3.4 기준) Iceberg 테이블(V2)에 대해
INSERT
,
DELETE
, *`UPDATE`*는 지원하지만,
MERGE INTO
구문은 아직 지원하지 않습니다.
* `MERGE INTO`는 현재 StarRocks의 *내부 테이블(Primary Key 테이블)*에 대해서만 사용할 수 있습니다. _ 따라서 StarRocks SQL 내에서 `MERGE INTO target_iceberg USING (SELECT _ FROM FILES(...))`와 같은 쿼리를 실행할 수 없습니다. ────────── 권장 해결 방안 원하시는 작업(MinIO의 Parquet 데이터를 Iceberg 테이블로 Merge/Upsert)을 수행하려면 다음 두 가지 중 하나를 선택해야 합니다. 방법 A: Spark를 사용하여 Merge 수행 (가장 권장) Spark의 Iceberg 커넥터를 사용하여 Parquet 파일을 읽고 `MERGE INTO`를 실행합니다.
Copy code
scala
// Spark에서 Parquet 파일을 읽어 뷰로 등록
val sourceDF = spark.read.parquet("<s3a://minio_path/data.parquet>")
sourceDF.createOrReplaceTempView("source_data")

// Iceberg 테이블로 MERGE INTO 실행
spark.sql("""
  MERGE INTO iceberg_catalog.db.target_table t
  USING source_data s
  ON t.id = s.id
  WHEN MATCHED THEN UPDATE SET *
  WHEN NOT MATCHED THEN INSERT *
""")
방법 B: StarRocks에서 INSERT OVERWRITE 사용 `MERGE INTO`가 꼭 필요한 것이 아니라 전체 데이터를 갱신하거나 특정 파티션을 교체하는 것이라면, StarRocks에서
FILES()
함수를 활용할 수 있습니다.
Copy code
sql
-- StarRocks에서 실행
INSERT OVERWRITE iceberg_catalog.db.target_table
SELECT * FROM FILES(
    "path" = "s3://...",
    "format" = "parquet",
    ...
);
요약하자면:
FILES()
구문은 StarRocks에서만 동작하며, StarRocks는 현재 Iceberg 대상의 `MERGE INTO`를 지원하지 않으므로, Spark를 쓰실 거라면
FILES()
대신 Spark의 데이터 로딩 방식을 사용하셔야 합니다.
Iceberg Catalog DML 가이드FILES() 함수 사용법 Referencesdata_source/catalog/iceberg/DML.mddata_source/catalog/iceberg/iceberg_catalog.mdquick_start/iceberg.mddata_source/catalog/iceberg/DDL.md
s
@Rocky Insert overwrite 사용하면 파티션이 다 날라가는거아냐? 중복데이터만 오버라이트되고, 중복 아니면 그냥 insert되는거야?
r
`INSERT OVERWRITE`의 동작 방식에 대해 명확히 설명해 드립니다. 1. 기본 동작: 전체 테이블 유실 위험 기본 설정에서 `INSERT OVERWRITE`를 사용하면, *쿼리 결과에 포함되지 않은 기존 파티션들이 모두 삭제(Truncate)*될 수 있습니다. * 예: 전체 테이블에 파티션 A, B, C가 있는데, `INSERT OVERWRITE`로 파티션 A 데이터만 넣으면 B와 C는 날아갑니다. 2. 해결책: Dynamic Overwrite (v3.4 이상) StarRocks v3.4 버전부터 지원되는 Dynamic Overwrite 기능을 사용하면, 소스 데이터에 존재하는 파티션만 교체하고 나머지 파티션은 그대로 유지할 수 있습니다.
Copy code
sql
-- 세션 변수 설정 또는 Hint 사용
SET dynamic_overwrite = true;

INSERT OVERWRITE iceberg_catalog.db.target_table
SELECT * FROM FILES(...);
이 설정을 켜면 소스 데이터(FILES)에 있는 파티션 키 값에 해당하는 파티션만 덮어쓰고, 데이터가 없는 파티션은 건드리지 않습니다. 3. 중복 데이터만 덮어쓰기? (Record-level Upsert 여부) 가장 중요한 부분입니다. `INSERT OVERWRITE`는 *파티션 단위의 교체*이지, 레코드 단위의 업서트(Upsert)가 아닙니다. * 동작 방식: 특정 파티션에 기존 데이터가 100건 있고, 새로 넣는 데이터가 10건(중복 포함)이라면, 기존 100건을 모두 지우고 새 데이터 10건만 남깁니다. * 원하시는 결과(중복은 교체, 새 데이터는 추가): 이것은 `MERGE INTO`의 영역입니다. `INSERT OVERWRITE`로 이를 구현하려면 소스 쿼리에서 직접 기존 테이블과 조인하여 "기존 데이터 + 새 데이터"를 합친 결과를 만들어 통째로 파티션에 부어야 합니다. 요약 * 파티션이 다 날아가나요? -> 기본은 그렇지만, `SET dynamic_overwrite = true;`를 쓰면 데이터가 있는 파티션만 교체됩니다. * 레코드별 중복 처리인가요? -> 아니요. 파티션 내의 기존 데이터를 모두 삭제하고 새 데이터로 갈아끼우는 방식입니다. 따라서 Iceberg 테이블에 대해 정교한 레코드 단위
MERGE
작업이 필요하시다면, 앞서 말씀드린 대로 *Spark*를 사용하시는 것이 현재로서는 가장 확실한 방법입니다. Referencesloading/InsertInto.mdsql-reference/sql-statements/loading_unloading/INSERT.mddata_source/catalog/iceberg/DML.md Referencesdata_source/catalog/iceberg/DML.mdloading/InsertInto.mdsql-reference/sql-statements/loading_unloading/INSERT.md