뷰 만들기

이 문서에서는 Unity 카탈로그에서 뷰를 만드는 방법을 보여 줍니다.

뷰는 메타스토어에 있는 하나 이상의 테이블과 뷰에서 구성된 읽기 전용 개체입니다. Unity 카탈로그 세 수준 네임스페이스의 세 번째 계층에 있습니다. 여러 스키마 및 카탈로그의 테이블 및 기타 뷰에서 뷰를 작성할 수 있습니다.

동적 뷰는 데이터 마스킹 외에도 행 및 열 수준 액세스 제어를 제공하는 데 사용할 수 있습니다.

뷰 만들기 구문의 예:

CREATE VIEW main.default.experienced_employee
  (id COMMENT 'Unique identification number', Name)
  COMMENT 'View for experienced employees'
AS SELECT id, name
   FROM all_employee
   WHERE working_years > 5;

참고 항목

뷰는 델타 테이블 이외의 데이터 원본에서 지원되는 경우 다른 실행 의미 체계를 가질 수 있습니다. Databricks는 테이블 또는 뷰 이름을 사용하여 데이터 원본을 참조하여 항상 뷰를 정의하는 것이 좋습니다. 경로 또는 URI를 지정하여 데이터 세트에 대한 뷰를 정의하면 데이터 거버넌스 요구 사항이 혼란스러울 수 있습니다.

요구 사항

보기를 만들려면 다음을 수행합니다.

  • 부모 카탈로그에 대한 USE CATALOG 권한과 부모 스키마에 대한 USE SCHEMACREATE TABLE 권한이 있어야 합니다. 메타스토어 관리자 또는 카탈로그 소유자가 이러한 모든 권한을 사용자에게 부여할 수 있습니다. 스키마 소유자는 스키마에 대해 USE SCHEMACREATE TABLE 권한을 사용자에게 부여할 수 있습니다.
  • 뷰에서 참조되는 테이블과 뷰를 읽을 수 있어야 합니다(SELECT 테이블 또는 뷰와 USE CATALOG 카탈로그 및 USE SCHEMA 스키마).
  • 뷰가 작업 영역 로컬 Hive 메타스토어의 테이블을 참조하는 경우 작업 영역 로컬 테이블이 포함된 작업 영역에서만 뷰에 액세스할 수 있습니다. 이러한 이유로 Databricks는 Unity 카탈로그 메타스토어에 있는 테이블 또는 뷰에서만 뷰를 만들 것을 권장합니다.
  • 델타 공유를 사용하여 공유된 뷰를 참조하는 뷰는 만들 수 없습니다. 델타 공유를 사용하여 안전하게 데이터 및 AI 자산 공유를 참조하세요.

보기를 읽으려면 필요한 권한은 컴퓨팅 유형 및 액세스 모드에 따라 달라집니다.

  • 공유 클러스터 및 SQL 웨어하우스의 경우 뷰 자체, USE CATALOG 부모 카탈로그 및 USE SCHEMA 부모 스키마에 필요합니다SELECT.
  • 단일 사용자 클러스터의 경우 부모 카탈로그 및 부모 스키마 외에도 USE CATALOG 보기에서 참조하는 모든 테이블과 USE SCHEMA 뷰에 있어야 합니다SELECT.

동적 보기를 만들거나 읽으려면 다음을 수행합니다.

  • 동적 보기에 대한 요구 사항은 공유 클러스터 또는 SQL 웨어하우스를 사용하여 동적 보기를 만들거나 읽어야 한다는 점을 제외하고 이전 섹션에 나열된 것과 동일합니다. 단일 사용자 클러스터는 사용할 수 없습니다.

보기 만들기

보기를 만들려면 다음 SQL 명령을 실행합니다. 괄호 안의 항목은 선택 사항입니다. 자리 표시자 값을 바꿉니다.

  • <catalog-name>: 카탈로그의 이름입니다.
  • <schema-name>: 스키마의 이름입니다.
  • <view-name>: 보기의 이름입니다.
  • <query>: 보기를 구성하는 데 사용되는 쿼리, 열, 테이블 및 보기입니다.

SQL

CREATE VIEW <catalog-name>.<schema-name>.<view-name> AS
SELECT <query>;

Python

spark.sql("CREATE VIEW <catalog-name>.<schema-name>.<view-name> AS "
  "SELECT <query>")

R

library(SparkR)

sql(paste("CREATE VIEW <catalog-name>.<schema-name>.<view-name> AS ",
  "SELECT <query>",
  sep = ""))

Scala

spark.sql("CREATE VIEW <catalog-name>.<schema-name>.<view-name> AS " +
  "SELECT <query>")

예를 들어, sales_raw 테이블의 열에서 sales_redacted이라는 뷰를 만들려면:

SQL

CREATE VIEW sales_metastore.sales.sales_redacted AS
SELECT
  user_id,
  email,
  country,
  product,
  total
FROM sales_metastore.sales.sales_raw;

Python

spark.sql("CREATE VIEW sales_metastore.sales.sales_redacted AS "
  "SELECT "
  "  user_id, "
  "  email, "
  "  country, "
  "  product, "
  "  total "
  "FROM sales_metastore.sales.sales_raw")

R

library(SparkR)

sql(paste("CREATE VIEW sales_metastore.sales.sales_redacted AS ",
  "SELECT ",
  "  user_id, ",
  "  email, ",
  "  country, ",
  "  product, ",
  "  total ",
  "FROM sales_metastore.sales.sales_raw",
  sep = ""))

Scala

spark.sql("CREATE VIEW sales_metastore.sales.sales_redacted AS " +
  "SELECT " +
  "  user_id, " +
  "  email, " +
  "  country, " +
  "  product, " +
  "  total " +
  "FROM sales_metastore.sales.sales_raw")

Databricks Terraform 공급자databricks_table을 사용하여 보기를 만들 수도 있습니다. databricks_views를 사용하여 보기 전체 이름 목록을 검색할 수 있습니다.

동적 뷰 만들기

Unity 카탈로그에서 동적 뷰를 사용하여 다음을 비롯한 세분화된 액세스 제어를 구성할 수 있습니다.

  • 열 또는 행 수준의 보안.
  • 데이터 마스킹.

참고 항목

동적 뷰를 사용하는 세분화된 액세스 제어는 단일 사용자액세스 모드의 클러스터에서 사용할 수 없습니다.

Unity 카탈로그에는 뷰에서 행, 열 또는 레코드에 액세스할 수 있는 사용자를 동적으로 제한할 수 있는 다음 함수가 도입되었습니다.

  • current_user(): 현재 사용자의 이메일 주소를 반환합니다.
  • is_account_group_member(): 현재 사용자가 특정 계정 수준 그룹의 멤버면 TRUE를 반환합니다. Unity 카탈로그 데이터는 동적 뷰에서 사용하는 것을 권장합니다.
  • is_member(): 현재 사용자가 특정 작업 영역 수준 그룹의 멤버면 TRUE를 반환합니다. 이 함수는 기존 Hive 메타스토어와의 호환성을 위해 제공됩니다. 계정 수준의 그룹 멤버 자격을 평가하지 않으므로 Unity 카탈로그 데이터에 대한 뷰와 함께 사용하지 마세요.

Azure Databricks는 사용자에게 보기에서 참조되는 테이블 및 뷰를 읽을 수 있는 기능을 부여하지 않는 것이 좋습니다.

다음 예제에서는 Unity 카탈로그에서 동적 뷰를 만드는 방법을 보여 줍니다.

서버 수준 사용 권한

동적 뷰를 사용하면 특정 사용자 또는 그룹이 액세스할 수 있는 열을 제한할 수 있습니다. 다음 예제에서는 auditors 그룹의 멤버만 sales_raw 테이블의 이메일 주소에 액세스할 수 있습니다. 쿼리 분석 중에 Apache Spark는 CASE 문을 리터럴 문자열 REDACTED 또는 이메일 주소 열의 실제 내용으로 바꿉니다. 다른 열은 정상적으로 반환됩니다. 이 전략은 쿼리 성능에 부정적인 영향을 주지 않습니다.

SQL

-- Alias the field 'email' to itself (as 'email') to prevent the
-- permission logic from showing up directly in the column name results.
CREATE VIEW sales_redacted AS
SELECT
  user_id,
  CASE WHEN
    is_account_group_member('auditors') THEN email
    ELSE 'REDACTED'
  END AS email,
  country,
  product,
  total
FROM sales_raw

Python

# Alias the field 'email' to itself (as 'email') to prevent the
# permission logic from showing up directly in the column name results.
spark.sql("CREATE VIEW sales_redacted AS "
  "SELECT "
  "  user_id, "
  "  CASE WHEN "
  "    is_account_group_member('auditors') THEN email "
  "  ELSE 'REDACTED' "
  "  END AS email, "
  "  country, "
  "  product, "
  "  total "
  "FROM sales_raw")

R

library(SparkR)

# Alias the field 'email' to itself (as 'email') to prevent the
# permission logic from showing up directly in the column name results.
sql(paste("CREATE VIEW sales_redacted AS ",
  "SELECT ",
  "  user_id, ",
  "  CASE WHEN ",
  "    is_account_group_member('auditors') THEN email ",
  "  ELSE 'REDACTED' ",
  "  END AS email, ",
  "  country, ",
  "  product, ",
  "  total ",
  "FROM sales_raw",
  sep = ""))

Scala

// Alias the field 'email' to itself (as 'email') to prevent the
// permission logic from showing up directly in the column name results.
spark.sql("CREATE VIEW sales_redacted AS " +
  "SELECT " +
  "  user_id, " +
  "  CASE WHEN " +
  "    is_account_group_member('auditors') THEN email " +
  "  ELSE 'REDACTED' " +
  "  END AS email, " +
  "  country, " +
  "  product, " +
  "  total " +
  "FROM sales_raw")

행 수준 권한

동적 뷰를 사용하면 행 또는 필드 수준까지 권한을 지정할 수 있습니다. 다음 예제에서는 트랜잭션 금액이 $1,000,000를 초과하는 경우 managers 그룹의 멤버만 트랜잭션 금액을 볼 수 있습니다. 일치하는 결과 중 다른 사용자의 결과는 필터링됩니다.

SQL

 CREATE VIEW sales_redacted AS
 SELECT
   user_id,
   country,
   product,
   total
 FROM sales_raw
 WHERE
   CASE
     WHEN is_account_group_member('managers') THEN TRUE
     ELSE total <= 1000000
   END;

Python

 spark.sql("CREATE VIEW sales_redacted AS "
   "SELECT "
   "  user_id, "
   "  country, "
   "  product, "
   "  total "
   "FROM sales_raw "
   "WHERE "
   "CASE "
   "  WHEN is_account_group_member('managers') THEN TRUE "
   "  ELSE total <= 1000000 "
   "END")

R

 library(SparkR)

 sql(paste("CREATE VIEW sales_redacted AS ",
   "SELECT ",
   "  user_id, ",
   "  country, ",
   "  product, ",
   "  total ",
   "FROM sales_raw ",
   "WHERE ",
   "CASE ",
   "  WHEN is_account_group_member('managers') THEN TRUE ",
   "  ELSE total <= 1000000 ",
   "END",
   sep = ""))

Scala

 spark.sql("CREATE VIEW sales_redacted AS " +
   "SELECT " +
   "  user_id, " +
   "  country, " +
   "  product, " +
   "  total " +
   "FROM sales_raw " +
   "WHERE " +
   "CASE " +
   "  WHEN is_account_group_member('managers') THEN TRUE " +
   "  ELSE total <= 1000000 " +
   "END")

데이터 마스킹

Unity 카탈로그의 뷰는 Spark SQL을 사용하므로 더 복잡한 SQL 식과 정규식을 사용하여 고급 데이터 마스킹을 구현할 수 있습니다. 다음 예에서는 모든 사용자가 이메일 도메인을 분석할 수 있지만 auditors 그룹의 멤버만 사용자의 전체 이메일 주소를 볼 수 있습니다.

SQL

-- The regexp_extract function takes an email address such as
-- user.x.lastname@example.com and extracts 'example', allowing
-- analysts to query the domain name.

CREATE VIEW sales_redacted AS
SELECT
  user_id,
  region,
  CASE
    WHEN is_account_group_member('auditors') THEN email
    ELSE regexp_extract(email, '^.*@(.*)$', 1)
  END
  FROM sales_raw

Python

# The regexp_extract function takes an email address such as
# user.x.lastname@example.com and extracts 'example', allowing
# analysts to query the domain name.

spark.sql("CREATE VIEW sales_redacted AS "
  "SELECT "
  "  user_id, "
  "  region, "
  "  CASE "
  "    WHEN is_account_group_member('auditors') THEN email "
  "    ELSE regexp_extract(email, '^.*@(.*)$', 1) "
  "  END "
  "  FROM sales_raw")

R

library(SparkR)

# The regexp_extract function takes an email address such as
# user.x.lastname@example.com and extracts 'example', allowing
# analysts to query the domain name.

sql(paste("CREATE VIEW sales_redacted AS ",
  "SELECT ",
  "  user_id, ",
  "  region, ",
  "  CASE ",
  "    WHEN is_account_group_member('auditors') THEN email ",
  "    ELSE regexp_extract(email, '^.*@(.*)$', 1) ",
  "  END ",
  "  FROM sales_raw",
  sep = ""))

Scala

// The regexp_extract function takes an email address such as
// user.x.lastname@example.com and extracts 'example', allowing
// analysts to query the domain name.

spark.sql("CREATE VIEW sales_redacted AS " +
  "SELECT " +
  "  user_id, " +
  "  region, " +
  "  CASE " +
  "    WHEN is_account_group_member('auditors') THEN email " +
  "    ELSE regexp_extract(email, '^.*@(.*)$', 1) " +
  "  END " +
  "  FROM sales_raw")

뷰 삭제

보기를 삭제하려면 보기의 소유자여야 합니다. 보기를 삭제하려면 다음 SQL 명령을 실행합니다.

DROP VIEW IF EXISTS catalog_name.schema_name.view_name;

다음 단계