Azure Databricks에서 테이블 복제

clone 명령을 사용하여 특정 버전의 Azure Databricks에서 기존 Delta Lake 테이블의 복사본을 만들 수 있습니다. 복제본은 깊거나 얕을 수 있습니다.

Azure Databricks는 Parquet 및 Iceberg 테이블 복제도 지원합니다. Delta Lake에 Parquet 및 Iceberg 테이블 증분 복제를 참조하세요.

Unity 카탈로그에서 클론을 사용하는 방법에 대한 자세한 내용은 Unity 카탈로그 테이블의 단순 복제본을 참조 하세요.

참고 항목

Databricks는 델타 공유를 사용하여 여러 조직에서 테이블에 대한 읽기 전용 액세스를 제공하는 것이 좋습니다. 델타 공유를 사용하여 안전하게 데이터 및 AI 자산 공유를 참조하세요.

형식 복제

  • 딥 클론은 원본 테이블 데이터를 기존 테이블의 메타데이터 외에도 복제 대상에 복사하는 복제본입니다. 이에 더해, 델타 테이블에 쓰는 스트림이 원본 테이블에서 중지되고 복제 대상에서 중지된 시점부터 시작할 수 있도록 스트림 메타데이터도 복제됩니다.
  • 단순 클론은 데이터 파일을 복제 대상에 복사하지 않는 클론입니다. 테이블 메타데이터는 원본과 동일합니다. 이러한 복제본은 만드는 데 비용이 더 적게 듭니다.

복제되는 메타데이터에는 스키마, 분할 정보, 고정 항목, null 허용 여부 등이 포함됩니다. 깊은 복제본의 경우에는 스트림 및 COPY INTO 메타데이터도 복제됩니다. 복제되지 않는 메타데이터는 테이블 설명과 사용자 정의 커밋 메타데이터입니다.

델타 복제 작업의 의미 체계는 무엇인가요?

Hive 메타스토어에 등록된 Delta 테이블 또는 테이블로 등록되지 않은 파일 컬렉션을 사용하여 작업하는 경우 복제본에는 다음과 같은 의미 체계가 있습니다.

Important

Databricks Runtime 13.3 LTS 이상에서 Unity 카탈로그 관리 테이블은 단순 클론을 지원합니다. Unity 카탈로그 테이블에 대한 복제 의미 체계는 다른 환경의 Delta Lake 복제 의미 체계와 크게 다릅니다. Unity 카탈로그 테이블의 단순 복제본을 참조 하세요.

  • 깊거나 얕은 복제본의 변경 내용은 원본 테이블이 아닌 복제본 자체에만 영향을 줍니다.
  • 얕은 복제본은 원본 디렉터리의 데이터 파일을 참조합니다. 원본 테이블에서 실행하는 vacuum 경우 클라이언트는 더 이상 참조된 데이터 파일을 읽을 수 없으며 throw FileNotFoundException 됩니다. 이 경우 단순 클론을 대체하는 클론을 실행하면 클론이 복구됩니다. 이 문제가 자주 발생하는 경우 원본 테이블에 의존하지 않는 깊은 복제본을 사용하는 것이 좋습니다.
  • 깊은 복제본은 복제된 원본에 의존하지 않지만, 데이터와 메타데이터를 모두 복사하기 때문에 만드는 데 비용이 더 많이 듭니다.
  • 해당 경로에 이미 테이블이 있는 대상으로 replace와 함께 복제하면 해당 경로에 델타 로그가 없는 경우 델타 로그가 생성됩니다. vacuum을 실행하여 기존 데이터를 모두 정리할 수 있습니다.
  • 기존 델타 테이블의 경우 새 메타데이터와 원본 테이블의 새 데이터를 포함하는 새 커밋이 만들어집니다. 이 새 커밋은 증분입니다. 즉, 마지막 복제 이후의 새 변경 내용만 테이블에 커밋됩니다.
  • 테이블을 복제하는 것은 Create Table As Select(CTAS)와 같지 않습니다. 복제는 데이터에 더해 원본 테이블의 메타데이터를 복사합니다. 복제는 구문도 더 간단합니다. 즉, 분할, 형식, 고정 항목, null 허용 여부 등을 지정하지 않아도 원본 테이블에서 해당 정보가 취해집니다.
  • 복제된 테이블은 원본 테이블에 대해 독립적인 기록을 갖습니다. 복제된 테이블의 시간 이동 쿼리는 원본 테이블에서 작업하는 것과 동일한 입력으로 작동하지 않습니다.

복제 구문 예제

다음 코드 예제에서는 깊고 단순한 클론을 만들기 위한 구문을 보여 줍니다.

SQL

CREATE TABLE delta.`/data/target/` CLONE delta.`/data/source/` -- Create a deep clone of /data/source at /data/target

CREATE OR REPLACE TABLE db.target_table CLONE db.source_table -- Replace the target

CREATE TABLE IF NOT EXISTS delta.`/data/target/` CLONE db.source_table -- No-op if the target table exists

CREATE TABLE db.target_table SHALLOW CLONE delta.`/data/source`

CREATE TABLE db.target_table SHALLOW CLONE delta.`/data/source` VERSION AS OF version

CREATE TABLE db.target_table SHALLOW CLONE delta.`/data/source` 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.forPath(spark, "/path/to/table")  # path-based tables, or
deltaTable = DeltaTable.forName(spark, "source_table")    # Hive metastore-based tables

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.forPath(spark, "/path/to/table")
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 delta.`/some/archive/path` CLONE my_prod_table

ML 모델 재현에 복제본 사용

기계 학습을 수행할 때는 ML 모델을 학습시킨 특정 버전의 테이블을 보관해야 할 수 있습니다. 향후 모델은 이 보관된 데이터 세트를 사용하여 테스트할 수 있습니다.

-- Trained model on version 15 of Delta table
CREATE TABLE delta.`/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;

복제를 사용하여 테이블 속성 재정의

참고 항목

Databricks Runtime 7.5 이상에서 사용할 수 있습니다.

테이블 속성 재정의는 다음과 같은 경우에 특히 유용합니다.

  • 다른 사업부와 데이터를 공유할 때 테이블에 소유자 또는 사용자 정보를 주석으로 추가합니다.
  • 델타 테이블 및 테이블 기록 또는 시간 이동 보관이 필요합니다. 보관 테이블에 대해 데이터 및 로그 보존 기간을 독립적으로 지정할 수 있습니다. 예시:

SQL

CREATE OR REPLACE TABLE archive.my_table CLONE prod.my_table
TBLPROPERTIES (
delta.logRetentionDuration = '3650 days',
delta.deletedFileRetentionDuration = '3650 days'
)
LOCATION 'xx://archive/my_table'

Python

dt = DeltaTable.forName(spark, "prod.my_table")
tblProps = {
"delta.logRetentionDuration": "3650 days",
"delta.deletedFileRetentionDuration": "3650 days"
}
dt.clone('xx://archive/my_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("xx://archive/my_table", isShallow = false, replace = true, properties = tblProps)