Создание представлений

В этой статье объясняется, как создавать представления в каталоге 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 SCHEMA и CREATE TABLE для родительской схемы. Администратор хранилища метаданных или владелец каталога могут предоставить вам все эти разрешения. Владелец схемы может предоставить вам разрешения на USE SCHEMA и CREATE TABLE для схемы.
  • Вы должны иметь возможность читать таблицы и представления, на которые ссылается представление (SELECT в таблице или представлении, а также USE CATALOG в каталоге и USE SCHEMA схеме).
  • Если представление ссылается на таблицы в локальном хранилище метаданных Hive рабочей области, доступ к представлению можно получить только из рабочей области, содержащей локальные таблицы рабочей области. По этой причине Databricks рекомендует создавать представления только из таблиц или представлений, которые находятся в хранилище метаданных каталога Unity.
  • Невозможно создать представление, которое ссылается на представление, которое было предоставлено вам совместно с помощью разностного общего доступа. Сведения о безопасном использовании разностного общего доступа см. в разделе "Общий доступ к данным и ресурсам ИИ".

Для чтения представления необходимые разрешения зависят от типа вычислений и режима доступа:

  • Для общих кластеров и хранилищ SQL вам потребуется SELECT представление, USE CATALOG в родительском каталоге и USE SCHEMA родительской схеме.
  • Для кластеров с одним пользователем необходимо также использовать SELECT все таблицы и представления, ссылающиеся на представления, в дополнение к USE CATALOG родительским каталогам и USE SCHEMA родительским схемам.

Чтобы создать или прочитать динамические представления, выполните приведенные действия.

  • Требования к динамическим представлениям совпадают с указанными в предыдущих разделах, за исключением того, что для создания или чтения динамического представления необходимо использовать общий кластер или хранилище 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_redacted из столбцов в таблице sales_raw, выполните следующие действия.

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")

Разрешения уровня строк

С помощью динамического представления можно указать разрешения на уровне строк или полей. В следующем примере только члены группы managers могут просматривать суммы транзакций, превышающих 1 000 000 долл. США. Для других пользователей соответствующие результаты будут отфильтрованы.

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 используют SQL Spark, можно реализовать расширенное маскирование данных с помощью более сложных выражений 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;

Следующие шаги