prefix 값이 나오지 않고 비어있는 이유는 StarRocks의 regexp_extract 함수 동작 방식 및 문자열 에스케이핑 처리 때문입니다.
regexp_extract(object_key, '^(.*)/[^/]+$', 1) 식에서 마지막 파일명 앞까지 추출하는 정규식이 정상적으로 매칭되지 않았거나, MinIO의 URL Encoding(예: / 대신 %2F 등으로 인코딩되어 들어오는 경우)으로 인해 슬래시(/) 구분자를 찾지 못했기 때문입니다.
StarRocks는 정규식 대신 내장 경로 처리 함수(parse_url_path)나 문자열 정규화 함수(url_decode) + reverse/`substr` 조합을 사용하면 훨씬 직관적이고 완벽하게 Prefix를 추출할 수 있습니다.
경로가 folder/sub/file.txt 일 때 folder/sub 또는 folder/sub/ 형태의 prefix를 안전하게 추출하도록 Routine Load의 prefix 컬럼 정의 부분을 수정합니다.
STOP ROUTINE LOAD FOR minio_metadata.minio_event_load;
CREATE ROUTINE LOAD minio_metadata.minio_event_load ON object_current_state
COLUMNS (
event_time_str,
event_name,
bucket,
raw_object_key,
size_bytes,
etag,
-- 1. URL Encoding 처리되어 들어오는 경우 디코딩 (예: %2F -> /)
object_key = url_decode(raw_object_key),
event_time = str_to_date(substr(event_time_str, 1, 19), '%Y-%m-%dT%H:%i:%s'),
-- 2. 슬래시(/)가 포함되어 있다면 마지막 슬래시 이전까지를 prefix로 추출
prefix = if(
locate('/', url_decode(raw_object_key)) > 0,
substr(url_decode(raw_object_key), 1, length(url_decode(raw_object_key)) - length(reverse(substr(reverse(url_decode(raw_object_key)), 1, locate('/', reverse(url_decode(raw_object_key))))))),
''
),
__deleted = if(event_name LIKE 's3:ObjectRemoved%', 1, 0),
object_id = md5(concat(bucket, ':', url_decode(raw_object_key)))
)
PROPERTIES (
"format" = "json",
"json_root" = "$.Records",
"jsonpaths" = "[\"$.eventTime\", \"$.eventName\", \"$.s3.bucket.name\", \"$.s3.object.key\", \"$.s3.object.size\", \"$.s3.object.eTag\"]",
"merge_condition" = "event_time"
)
FROM KAFKA (
"kafka_broker_list" = "192.168.x.x:9092", -- 실제 Kafka Broker IP로 수정
"kafka_topic" = "minio-bucket-events",
"property.group.id" = "starrocks_minio_events",
"property.kafka_default_offsets" = "OFFSET_BEGINNING"
);
단순화 팁: 만약 정규식을 선호하신다면
regexp_extract(url_decode(raw_object_key), '^(.*)/', 1)구문으로 작성하셔도 슬래시 전까지의 Prefix가 추출됩니다.
이미 테이블에 들어와서 Prefix가 비어 있는 기존 데이터들은 아래 UPDATE 쿼리로 한 번에 복구할 수 있습니다.
UPDATE object_current_state
SET
object_key = url_decode(object_key),
prefix = if(
locate('/', url_decode(object_key)) > 0,
regexp_extract(url_decode(object_key), '^(.*)/', 1),
''
)
WHERE prefix = '' AND object_key LIKE '%/%';
업데이트 후 데이터베이스에서 직접 조회하여 prefix 컬럼에 값(a/b, images/2026 등)이 제대로 채워졌는지 확인합니다.
-- 1. 테이블 원본 데이터 prefix 확인
SELECT bucket, object_key, prefix, size_bytes FROM object_current_state LIMIT 10;
-- 2. View 집계 확인
SELECT * FROM v_prefix_summary;