Azure Databricks에서 테이블 복제
clone
명령을 사용하여 특정 버전의 Azure Databricks에서 기존 Delta Lake 테이블의 복사본을 만들 수 있습니다. 복제본은 깊거나 얕을 수 있습니다.
Azure Databricks는 Parquet 및 Iceberg 테이블 복제도 지원합니다. Delta Lake에 Parquet 및 Iceberg 테이블 증분 복제를 참조하세요.
Unity 카탈로그에서 클론을 사용하는 방법에 대한 자세한 내용은 Unity 카탈로그 테이블의 단순 복제본을 참조 하세요.
참고 항목
Databricks는 델타 공유를 사용하여 여러 조직에서 테이블에 대한 읽기 전용 액세스를 제공하는 것이 좋습니다. Delta Sharing이란?을 참조하세요.
형식 복제
- 딥 클론은 원본 테이블 데이터를 기존 테이블의 메타데이터 외에도 복제 대상에 복사하는 복제본입니다. 이에 더해, 델타 테이블에 쓰는 스트림이 원본 테이블에서 중지되고 복제 대상에서 중지된 시점부터 시작할 수 있도록 스트림 메타데이터도 복제됩니다.
- 단순 클론은 데이터 파일을 복제 대상에 복사하지 않는 클론입니다. 테이블 메타데이터는 원본과 동일합니다. 이러한 복제본은 만드는 데 비용이 더 적게 듭니다.
복제되는 메타데이터에는 스키마, 분할 정보, 고정 항목, null 허용 여부 등이 포함됩니다. 딥 클론만의 경우 스트림 및 COPY INTO 메타데이터도 복제됩니다. 복제되지 않는 메타데이터는 테이블 설명과 사용자 정의 커밋 메타데이터입니다.
델타 복제 작업의 의미 체계는 무엇인가요?
Hive 메타스토어에 등록된 Delta 테이블 또는 테이블로 등록되지 않은 파일 컬렉션을 사용하여 작업하는 경우 복제본에는 다음과 같은 의미 체계가 있습니다.
Important
Databricks Runtime 13.3 LTS 이상에서 Unity 카탈로그 관리 테이블은 단순 클론을 지원합니다. Unity 카탈로그 테이블에 대한 복제 의미 체계는 다른 환경의 Delta Lake 복제 의미 체계와 크게 다릅니다. Unity 카탈로그 테이블의 단순 복제본을 참조 하세요.
- 깊거나 얕은 복제본의 변경 내용은 원본 테이블이 아닌 복제본 자체에만 영향을 줍니다.
- 얕은 복제본은 원본 디렉터리의 데이터 파일을 참조합니다. 원본 테이블에서 실행하는
vacuum
경우 클라이언트는 더 이상 참조된 데이터 파일을 읽을 수 없으며 throwFileNotFoundException
됩니다. 이 경우 단순 클론을 대체하는 클론을 실행하면 클론이 복구됩니다. 이 문제가 자주 발생하는 경우 원본 테이블에 의존하지 않는 깊은 복제본을 사용하는 것이 좋습니다. - 깊은 복제본은 복제된 원본에 의존하지 않지만, 데이터와 메타데이터를 모두 복사하기 때문에 만드는 데 비용이 더 많이 듭니다.
- 해당 경로에 이미 테이블이 있는 대상으로
replace
와 함께 복제하면 해당 경로에 델타 로그가 없는 경우 델타 로그가 생성됩니다.vacuum
을 실행하여 기존 데이터를 모두 정리할 수 있습니다. - 기존 델타 테이블의 경우 새 메타데이터와 원본 테이블의 새 데이터를 포함하는 새 커밋이 만들어집니다. 이 새 커밋은 증분입니다. 즉, 마지막 복제 이후의 새 변경 내용만 테이블에 커밋됩니다.
- 테이블을 복제하는 것은
Create Table As Select
(CTAS
)와 같지 않습니다. 복제는 데이터에 더해 원본 테이블의 메타데이터를 복사합니다. 복제는 구문도 더 간단합니다. 즉, 분할, 형식, 고정 항목, null 허용 여부 등을 지정하지 않아도 원본 테이블에서 해당 정보가 취해집니다. - 복제된 테이블은 원본 테이블에 대해 독립적인 기록을 갖습니다. 복제된 테이블의 시간 이동 쿼리는 원본 테이블에서 작업하는 것과 동일한 입력으로 작동하지 않습니다.
복제 구문 예제
다음 코드 예제에서는 깊고 단순한 클론을 만들기 위한 구문을 보여 줍니다.
SQL
CREATE TABLE target_table CLONE source_table; -- Create a deep clone of source_table as target_table
CREATE OR REPLACE TABLE target_table CLONE source_table; -- Replace the target
CREATE TABLE IF NOT EXISTS target_table CLONE source_table; -- No-op if the target table exists
CREATE TABLE target_table SHALLOW CLONE source_table;
CREATE TABLE target_table SHALLOW CLONE source_table VERSION AS OF version;
CREATE TABLE target_table SHALLOW CLONE source_table TIMESTAMP AS OF timestamp_expression; -- timestamp can be like “2019-01-01” or like date_sub(current_date(), 1)
Python
from delta.tables import *
deltaTable = DeltaTable.forName(spark, "source_table")
deltaTable.clone(target="target_table", isShallow=True, replace=False) # clone the source at latest version
deltaTable.cloneAtVersion(version=1, target="target_table", isShallow=True, replace=False) # clone the source at a specific version
# clone the source at a specific timestamp such as timestamp="2019-01-01"
deltaTable.cloneAtTimestamp(timestamp="2019-01-01", target="target_table", isShallow=True, replace=False)
Scala
import io.delta.tables._
val deltaTable = DeltaTable.forName(spark, "source_table")
deltaTable.clone(target="target_table", isShallow=true, replace=false) // clone the source at latest version
deltaTable.cloneAtVersion(version=1, target="target_table", isShallow=true, replace=false) // clone the source at a specific version
deltaTable.cloneAtTimestamp(timestamp="2019-01-01", target="target_table", isShallow=true, replace=false) // clone the source at a specific timestamp
구문 세부 정보는 CREATE TABLE CLONE참조하세요.
복제본 메트릭
CLONE
는 작업이 완료되면 다음과 같은 메트릭을 단일 행 DataFrame으로 보고합니다.
-
source_table_size
: 복제되는 원본 테이블의 크기(바이트). -
source_num_of_files
: 원본 테이블의 파일 수. -
num_removed_files
: 파일이 대체되는 경우, 현재 테이블에서 제거되는 파일의 수. -
num_copied_files
: 원본에서 복사된 파일의 수(얕은 복제본의 경우 0). -
removed_files_size
: 현재 테이블에서 제거되는 파일의 크기(바이트). -
copied_files_size
: 테이블에 복사된 파일의 크기(바이트).
사용 권한
Azure Databricks 테이블 액세스 제어 및 클라우드 공급자에 대한 권한을 구성해야 합니다.
테이블 액세스 제어
깊은 복제본과 얕은 복제본 양쪽 모두 다음과 같은 권한이 필요합니다.
- 원본 테이블에 대한
SELECT
권한. -
CLONE
을 사용하여 새 테이블을 만드는 경우, 테이블을 만드는 데이터베이스에 대한CREATE
권한. -
CLONE
을 사용하여 테이블을 대체하는 경우, 테이블에 대한MODIFY
권한.
클라우드 공급자 권한
깊은 복제본을 만든 경우, 깊은 복제본을 읽는 모든 사용자는 복제본 디렉터리에 대한 읽기 권한이 필요합니다. 복제본을 변경하려는 사용자는 복제본 디렉터리에 대한 쓰기 권한이 필요합니다.
얕은 복제본을 만든 경우, 얕은 복제본을 읽는 모든 사용자는 (얕은 복제본의 경우 데이터 파일이 원본 테이블에 남아 있으므로) 원본 테이블의 파일에 대한 읽기 권한과 복제본 디렉터리에 대한 읽기 권한이 필요합니다. 복제본을 변경하려는 사용자는 복제본 디렉터리에 대한 쓰기 권한이 필요합니다.
데이터 보관에 복제본 사용
딥 클론을 사용하여 보관을 위해 특정 시점에 테이블의 상태를 유지할 수 있습니다. 딥 클론을 증분 방식으로 동기화하여 재해 복구를 위해 원본 테이블의 업데이트된 상태를 유지할 수 있습니다.
-- Every month run
CREATE OR REPLACE TABLE archive_table CLONE my_prod_table
ML 모델 재현에 복제본 사용
기계 학습을 수행할 때는 ML 모델을 학습시킨 특정 버전의 테이블을 보관해야 할 수 있습니다. 향후 모델은 이 보관된 데이터 세트를 사용하여 테스트할 수 있습니다.
-- Trained model on version 15 of Delta table
CREATE TABLE model_dataset CLONE entire_dataset VERSION AS OF 15
프로덕션 테이블에 대한 단기 실험에 복제본 사용
테이블을 손상시키지 않고 프로덕션 테이블에서 워크플로를 테스트하려면 얕은 복제본을 만들면 됩니다. 이렇게 하면 모든 프로덕션 데이터를 포함하지만 프로덕션 워크로드에는 영향을 주지 않는 복제된 테이블에서 임의의 워크플로를 실행할 수 있습니다.
-- Perform shallow clone
CREATE OR REPLACE TABLE my_test SHALLOW CLONE my_prod_table;
UPDATE my_test WHERE user_id is null SET invalid=true;
-- Run a bunch of validations. Once happy:
-- This should leverage the update information in the clone to prune to only
-- changed files in the clone if possible
MERGE INTO my_prod_table
USING my_test
ON my_test.user_id <=> my_prod_table.user_id
WHEN MATCHED AND my_test.user_id is null THEN UPDATE *;
DROP TABLE my_test;
복제를 사용하여 테이블 속성 재정의
테이블 속성 재정의는 다음과 같은 경우에 특히 유용합니다.
- 다른 사업부와 데이터를 공유할 때 테이블에 소유자 또는 사용자 정보를 주석으로 추가합니다.
- 델타 테이블 및 테이블 기록 또는 시간 이동 보관이 필요합니다. 보관 테이블에 대해 데이터 및 로그 보존 기간을 독립적으로 지정할 수 있습니다. 예시:
SQL
CREATE OR REPLACE TABLE archive_table CLONE prod.my_table
TBLPROPERTIES (
delta.logRetentionDuration = '3650 days',
delta.deletedFileRetentionDuration = '3650 days'
)
Python
dt = DeltaTable.forName(spark, "prod.my_table")
tblProps = {
"delta.logRetentionDuration": "3650 days",
"delta.deletedFileRetentionDuration": "3650 days"
}
dt.clone(target="archive_table", isShallow=False, replace=True, tblProps)
Scala
val dt = DeltaTable.forName(spark, "prod.my_table")
val tblProps = Map(
"delta.logRetentionDuration" -> "3650 days",
"delta.deletedFileRetentionDuration" -> "3650 days"
)
dt.clone(target="archive_table", isShallow = false, replace = true, properties = tblProps)