Create views | Databricks on AWS [2022/8/25時点]の翻訳です。
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
本書では、Unity Catalogでどのようにビューを作成するのかを説明します。
ビューはメタストアにある1つい上のテーブルやビューから構成される読み取り専用オブジェクトです。Unity Catalogの3レベル名前空間の3層目に存在します。ビューは複数のスキーマ、カタログに存在するテーブルやビューから作成することができます。
ダイナミックビューは、行列のアクセス制御、データマスキングを提供するために使用されます。
ビュー作成構文のサンプルは以下のようになります。
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;
要件
- 親カタログに対する
USAGE
権限、親スキーマに対するUSAGE
、CREATE
権限が必要です。メタストア管理者、カタログオーナーはこれらの権限全てを付与することができます。スキーマオーナーは、スキーマに対するUSAGE
、CREATE
権限を付与することができます。 - ビューで参照されるテーブル、ビューを読み込む権限が必要です。(テーブル、ビューに対する
SELECT
、カタログ、スキーマに対するUSAGE
)
注意
Single Userアクセスモードのクラスターからビューを読み込むためには、参照されるすべてのテーブルとビューに対するSELECT
権限が必要となります。
ビューがワークスペースローカルのHiveメタストアのテーブルを参照している場合、このビューはワークスペースローカルのテーブルを保持しているワークスペースからしか参照できません。このため、Unity Catalogに存在するテーブルやビューからビューを作成することをお勧めします。
ビューの作成
ビューを作成するには、以下のSQLコマンドを実行します。括弧内のアイテムはオプションです。プレースホルダーの値を置き換えてください。
-
<catalog_name>
: カタログの名称。 -
<schema_name>
: スキーマの名称。 -
<view_name>
: ビューの名称。 -
<query>
: ビューを構成するために使用されるクエリー、カラム、テーブル、ビュー。
CREATE VIEW <catalog_name>.<schema_name>.<view_name> AS
SELECT <query>;
spark.sql("CREATE VIEW <catalog_name>.<schema_name>.<view_name> AS "
"SELECT <query>")
library(SparkR)
sql(paste("CREATE VIEW <catalog_name>.<schema_name>.<view_name> AS ",
"SELECT <query>",
sep = ""))
spark.sql("CREATE VIEW <catalog_name>.<schema_name>.<view_name> AS " +
"SELECT <query>")
例えば、sales_raw
テーブルのカラムからsales_redacted
というビューを作成するには以下を実行します。
CREATE VIEW sales_metastore.sales.sales_redacted AS
SELECT
user_id,
email,
country,
product,
total
FROM sales_metastore.sales.sales_raw;
spark.sql("CREATE VIEW sales_metastore.sales.sales_redacted AS "
"SELECT "
" user_id, "
" email, "
" country, "
" product, "
" total "
"FROM sales_metastore.sales.sales_raw")
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 = ""))
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 providerとdatabricks_tableを用いることでビューを作成することができます。databricks_viewsを用いることで、ビュー名称のリストを取得することができます。
ダイナミックビューの作成
Unity Catalogでは、以下を含むきめ細かいアクセスコントロールを設定するためにダイナミックビューを活用することができます。
- 行列レベルでのセキュリティ。
- データマスキング。
注意
シングルユーザーアクセスモードでは、ダイナミックビューを用いたきめ細かいアクセスコントロールはサポートされていません。
Unity Catalogでは、どのユーザーが行、列、ビュー内のレコードにアクセスできるのかを動的に制限するための以下の関数を導入しています。
-
current_user()
: 現在のユーザーのメールアドレスを返却します。 -
is_account_group_member()
: 現在のユーザーが特定のアカウントレベルグループのメンバーである場合にはTRUE
を返却します。Unity Catalogのデータに対するダイナミックビューでの使用を推奨します。 -
is_member()
: 現在のユーザーが特定のワークスペースレベルのグループのメンバーの場合にはTRUE
を返却します。この関数は、既存のHiveメタストアとの互換性のために提供されています。アカウントレベルグループのメンバーシップを評価しないので、Unity Catalogデータに対するビューでは使用しないでください。
以下のサンプルでは、Unity Catalogのダイナミックビューをどのように作成するのかを説明します。
列レベルのアクセス権
ダイナミックビューを用いることで、特定のユーザーやグループがアクセスできるカラムを限定することができます。以下の例では、auditors
グループのメンバーのみがsales_raw
テーブルのメールアドレスにアクセスすることができます。クエリーの解析中にApache SparkはCASE
文を文字列リテラルREDACTED
か、メールアドレスカラムの実際の値で置き換えます。他のカラムは通常通り返却されます。この戦略はクエリー性能にネガティブな影響を及ぼしません。
-- 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
# 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")
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 = ""))
// 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を超えるトランザクションを参照することができます。他のユーザーに対してはフィルタリングされた結果が返却されます。
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;
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")
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 = ""))
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 CatalogのビューではSpark SQLを使用するので、より複雑なSQLエクスプレッションや正規表現を用いて高度なデータマスキングを実装することができます。以下の例では、すべてのユーザーはメールのドメインを解析できますが、auditors
グループのメンバーはメールアドレス全体を参照できます。
-- 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
# 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")
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 = ""))
// 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")