共用方式為

行筛选器和列掩码

本页提供了有关使用行筛选器、列掩码和映射表以筛选表中敏感数据的指导和示例。 这些功能需要 Unity 目录。 如果要查找基于标记的集中式筛选和掩码方法,请参阅 Unity 目录基于属性的访问控制(ABAC)。 ABAC 使你能够使用受治理的标记管理策略,并在多个表中一致地应用它们。

什么是行筛选器?

行筛选器让你可以向表应用筛选器,以便查询仅返回符合筛选器的行。 行筛选器作为 SQL 用户定义函数 (UDF) 实现。 Python 和 Scala UDF 也受支持,但仅当它们包装在 SQL UDF 中时才受支持。

什么是列过滤?

列过滤让你可以将过滤函数应用于表列。 掩码函数在查询运行时进行计算,将目标列的每个引用替换为掩码函数的结果。 对于大多数用例,列过滤决定了是返回原始列值还是根据调用用户的标识对其进行修订。 列掩码是一些表达式,它们可以直接编写为 SQL UDF,也可以是编写成 Python 或 Scala UDF 并封装在 SQL UDF 中。

每个表列只能应用一个掩码函数。 过滤函数接收列的未过滤值作为输入,并返回过滤值作为结果。 过滤函数的返回值应与要过滤的列的类型相同。 掩码函数还可以采用其他列作为输入参数,并在其掩码逻辑中使用这些列。

比较筛选器、基于属性的访问控制(ABAC)和动态视图

行筛选器、列掩码、ABAC 策略和动态视图在查询时都会评估逻辑,但在应用和管理逻辑的方式上有所不同。

  • 如果需要一种可缩放的集中式方法来基于受治理的标记筛选和屏蔽,请使用 ABAC。 Databricks 建议对大多数用例使用 ABAC。
  • 需要特定于表的逻辑且尚未使用 ABAC 时,请使用 行筛选器和列掩码
  • 当 SQL 逻辑涉及多个表,或当你需要使用 Delta Sharing 共享已筛选的数据(在该场景下不会强制执行 ABAC)时,请使用动态视图

有关何时使用每个项的完整比较和指南,请参阅 何时使用每个访问控制机制

开始之前

若要向表添加行筛选器和列掩码,必须具有:

此外,还必须满足以下要求:

  • 若要分配向表添加行过滤器或列掩码的函数,必须对该函数具有 EXECUTE 权限、对架构具有 USE SCHEMA 权限、对父目录具有 USE CATALOG 权限。
  • 如果要在创建表时添加筛选器或掩码,还必须具有该架构的 CREATE TABLE 权限。
  • 如果要向 现有 表添加筛选器或掩码,则必须是表所有者或 MANAGE 具有该表的特权。

若要访问具有行筛选器或列掩码的表,计算资源必须满足下列要求之一:

  • SQL 仓库。
  • Databricks Runtime 12.2 LTS 或更高版本上的标准访问模式(以前共享访问模式)。
  • Databricks Runtime 15.4 LTS 或更高版本上的专用访问模式(以前是单用户访问模式)。

不能在 Databricks Runtime 15.3 或更低版本上使用专用计算读取行筛选器或列掩码。

若要利用 Databricks Runtime 15.4 LTS 及更高版本中提供的数据筛选,还必须验证工作区是否启用了无服务器计算,因为支持行筛选器和列掩码的数据筛选功能在无服务器计算上运行。 当你使用配置为专用访问模式的计算资源来读取使用行过滤器或列过滤的表时,可能会被收取无服务器计算资源的费用。 对这些表的写入作仅在 DBR 16.3 及更高版本上受支持,并且必须使用支持的模式,例如 MERGE INTO

小窍门

若要基于受治理的标记应用筛选和屏蔽策略,而不是按表分配策略,请考虑使用 ABAC。 请参阅 Unity 目录基于属性的访问控制(ABAC)。

应用行筛选器

若要创建行筛选器,请编写一个函数 (UDF),以定义筛选器策略,然后将其应用于表。 每个表只能有一个行筛选器。 行筛选器接受零个或多个输入参数,其中每个输入参数绑定到相应表的一列。

可以使用目录资源管理器或 SQL 命令应用行筛选器。 目录资源管理器说明假定你已经创建了一个函数,并在 Unity 目录中注册了它。 SQL 说明包括创建行筛选器函数并将其应用于表的示例。

注意

如果使用 Lakeflow 声明性管道,可以使用 Lakeflow 声明性管道 Python API 创建使用行筛选器和列掩码的流式处理表或具体化视图。 请参阅发布具有行筛选器和列掩码的表

目录资源管理器

  1. 在 Azure Databricks 工作区中,单击 “数据”图标。目录

  2. 浏览或搜索要筛选的表。

  3. 在“ 概述 ”选项卡上的 “行筛选器”下,单击“ 添加筛选器”。

  4. 在“添加行筛选器”对话框中,选择包含筛选器函数的目录和架构,然后选择该函数

  5. 在展开的对话框中,查看函数定义并选择与函数语句中包含的列匹配的表列。

  6. 单击“添加” 。

若要从表中移除筛选器,请单击“fx 行筛选器”,然后单击“删除”

SQL

若要创建行筛选器,然后将其添加到现有表,请使用 CREATE FUNCTION 并使用 ALTER TABLE应用函数。 还可以在使用 CREATE TABLE 创建表时应用函数。

  1. 创建行筛选器:

    CREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
    RETURN {filter clause whose output must be a boolean};
    
  2. 使用列名将行筛选器应用于表:

    ALTER TABLE <table_name> SET ROW FILTER <function_name> ON (<column_name>, ...);
    

其他语法示例

  • 使用与函数参数匹配的常量文本将行筛选器应用于表:

    ALTER TABLE <table_name> SET ROW FILTER <function_name> ON (<constant_literal>, ...);
    
  • 从表中删除行筛选器:

    ALTER TABLE <table_name> DROP ROW FILTER;
    
  • 修改行筛选器:

    Run a DROP FUNCTION statement to drop the existing function, or use CREATE OR REPLACE FUNCTION to replace it.
    
  • 删除行筛选器:

    ALTER TABLE <table_name> DROP ROW FILTER;
    DROP FUNCTION <function_name>;
    

    注意

    在删除函数之前,必须执行 ALTER TABLE ... DROP ROW FILTER 命令。 否则,表将处于无法访问的状态。

    如果以这种方式无法访问表,请使用 ALTER TABLE <table_name> DROP ROW FILTER; 更改表并删除孤立行筛选器引用。

另请参阅 ROW FILTER 条款

行筛选器示例

此示例创建一个适用于国家/地区 adminUS 组成员的 SQL 用户定义函数。

当为 sales 表应用此示例函数时,admin 组的成员可以访问表中的所有记录。 如果函数由非管理员调用,则 RETURN_IF 条件将失败,并计算 region='US' 表达式,从而筛选表以仅显示 US 区域中的记录。

CREATE FUNCTION us_filter(region STRING)
RETURN IF(IS_ACCOUNT_GROUP_MEMBER('admin'), true, region='US');

将函数作为行筛选器应用于表。 sales 表中的后续查询则会返回行子集。

CREATE TABLE sales (region STRING, id INT);
ALTER TABLE sales SET ROW FILTER us_filter ON (region);

禁用行筛选器。 sales 表中的未来用户查询则会返回表中的所有行。

ALTER TABLE sales DROP ROW FILTER;

创建一个表,将该表的函数作为 CREATE TABLE 语句的一部分应用为行筛选器。 sales 表中的每个未来查询则会返回行子集。

CREATE TABLE sales (region STRING, id INT)
WITH ROW FILTER us_filter ON (region);

应用列掩码

若要应用列掩码,请创建一个函数(UDF),并将其应用于表列。

可以使用目录资源管理器或 SQL 命令应用列掩码。 目录资源管理器说明假定你已经创建了一个函数,并在 Unity 目录中注册了它。 SQL 说明包括创建列掩码函数并将其应用于表列的示例。

注意

如果使用 Lakeflow 声明性管道,可以使用 Lakeflow 声明性管道 Python API 创建使用行筛选器和列掩码的流式处理表或具体化视图。 请参阅发布具有行筛选器和列掩码的表

目录资源管理器

  1. 在 Azure Databricks 工作区中,单击 “数据”图标。目录

  2. 浏览或搜索表。

  3. 在“概述”选项卡上,找到要向其应用列掩码的行,然后单击 “编辑”图标“掩码”编辑图标。

  4. 在“添加列掩码”对话框中,选择包含筛选器函数的目录和架构,然后选择该函数

  5. 在展开的对话框中,查看函数定义。 如果函数包含除要屏蔽的列之外的任何参数,请选择要用于转换这些附加函数参数的表列。

  6. 单击“添加” 。

要从表中删除列掩码,请单击表行中的“fx 列掩码”,然后单击“移除”

SQL

若要创建列掩码并将其添加到现有表列,请使用 CREATE FUNCTION 并使用 ALTER TABLE 应用掩码函数。 还可以在使用 CREATE TABLE 创建表时应用函数。

使用 SET MASK 应用掩码函数。 在 MASK 子句中,可以使用任何 Azure Databricks 内置运行时函数或调用其他用户定义函数。 常见用例包括通过使用 current_user( ) 检查运行该函数的调用用户的身份或使用 is_account_group_member( ) 获取他们所属的组。 有关详细信息,请参阅 Column mask 子句内置函数

  1. 创建列过滤:

    CREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
    RETURN {expression with the same type as the first parameter};
    
  2. 将列掩码应用于现有表中的列:

    ALTER TABLE <table_name> ALTER COLUMN <col_name> SET MASK <mask_func_name> USING COLUMNS <additional_columns>;
    

其他语法示例

  • 使用与函数参数匹配的常量文本将列掩码应用于现有表中的列:

    ALTER TABLE <table_name> ALTER COLUMN <col_name> SET MASK <mask_func_name> USING COLUMNS (<constant_name>, ...);
    
  • 从表的列中删除列过滤:

    ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;
    
  • 修改列掩码,DROP 现有函数或使用 CREATE OR REPLACE TABLE

  • 删除列任务:

    ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;
    DROP FUNCTION <function_name>;
    

    注意

    在删除函数前必须执行 ALTER TABLE 命令,否则表将处于不可访问状态。

    如果以这种方式无法访问表,请使用 ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK; 更改表并删除孤立过滤参考。

列过滤示例

在此示例中,你将创建一个用户定义的函数来屏蔽 ssn 列,以便只有属于 HumanResourceDept 组成员的用户才能查看该列中的值。

CREATE FUNCTION ssn_mask(ssn STRING)
  RETURN CASE WHEN is_account_group_member('HumanResourceDept') THEN ssn ELSE '***-**-****' END;

将新函数作为列过滤应用于表。 可以在创建表时或之后添加列掩码。

--Create the `users` table and apply the column mask in a single step:

CREATE TABLE users (
  name STRING,
  ssn STRING MASK ssn_mask);
--Create the `users` table and apply the column mask after:

CREATE TABLE users
  (name STRING, ssn STRING);

ALTER TABLE users ALTER COLUMN ssn SET MASK ssn_mask;

当查询用户不是 ssn 组的成员时,对该表的查询现在会返回屏蔽的 HumanResourceDept 列值:

SELECT * FROM users;
  James  ***-**-****

若要禁用列掩码,以便查询返回 ssn 列中的原始值,请执行以下操作:

ALTER TABLE users ALTER COLUMN ssn DROP MASK;

使用映射表创建访问控制列表

若要实现行级别安全性,请考虑定义映射表(或访问控制列表)。 一个全面的映射表会对原始表中哪些数据行可供某些用户或组访问进行编码。 映射表非常有用,因为它们通过直接联接提供与事实数据表的简单集成。

此方法解决了许多包含自定义要求的用例。 示例包括:

  • 根据登录用户施加限制,同时顾及特定用户组的不同规则。
  • 创建复杂的层次结构(如组织结构),这些层次结构需要不同的规则集。
  • 从外部源系统复制复杂的安全模型。

通过采用映射表,可以成功处理这些具有挑战性的场景,并确保可靠的行级和列级安全实现。

映射表示例

使用映射表检查当前用户是否在列表中:

USE CATALOG main;

创建新的映射表:

DROP TABLE IF EXISTS valid_users;

CREATE TABLE valid_users(username string);
INSERT INTO valid_users
VALUES
  ('fred@databricks.com'),
  ('barney@databricks.com');

创建新筛选器:

注意

除了作为调用方运行的检查用户上下文的函数(例如 CURRENT_USERIS_ACCOUNT_GROUP_MEMBER 函数)外,所有筛选器都以定义者的权限运行。

在此示例中,该函数检查当前用户是否位于 valid_users 表中。 如果找到用户,该函数将返回 true。

DROP FUNCTION IF EXISTS row_filter;

CREATE FUNCTION row_filter()
  RETURN EXISTS(
    SELECT 1 FROM valid_users v
    WHERE v.username = CURRENT_USER()
);

以下示例在创建表期间应用行筛选器。 以后还可以使用 ALTER TABLE 语句添加筛选器。 将筛选器应用于未指定的列时,请使用 ON () 语法。 对于特定列,请使用 ON (column);。 有关详细信息,请参阅 “参数”。

DROP TABLE IF EXISTS data_table;

CREATE TABLE data_table
  (x INT, y INT, z INT)
  WITH ROW FILTER row_filter ON ();

INSERT INTO data_table VALUES
  (1, 2, 3),
  (4, 5, 6),
  (7, 8, 9);

从表中选择数据。 只有当用户位于 valid_users 表中时,才会返回数据。

SELECT * FROM data_table;

创建一个映射表,其中包含应始终有权查看表中所有行的帐户,而不考虑列值:

CREATE TABLE valid_accounts(account string);
INSERT INTO valid_accounts
VALUES
  ('admin'),
  ('cstaff');

现在,创建一个 SQL UDF,如果行中所有列的值小于 5,或者调用用户是上述映射表的成员,则该 SQL UDF 返回 true

CREATE FUNCTION row_filter_small_values (x INT, y INT, z INT)
  RETURN (x < 5 AND y < 5 AND z < 5)
  OR EXISTS(
    SELECT 1 FROM valid_accounts v
    WHERE IS_ACCOUNT_GROUP_MEMBER(v.account));

最后,将 SQL UDF 作为行筛选器应用于表:

ALTER TABLE data_table SET ROW FILTER row_filter_small_values ON (x, y, z);

支持和限制

所有 Azure Databricks 功能或所有计算资源都不支持行筛选器和列掩码。 本部分列出了受支持的功能和限制。

支持的功能和格式

此受支持功能列表并不详尽。 会列出某些项,是因为它们在公共预览版期间不受支持。

  • 支持用于适用于 SQL 工作负载的 Databricks SQL 和 Databricks 笔记本。

  • 支持具有 MODIFY 特权的用户的 DML 命令。 筛选器和掩码适用于 UPDATEDELETE 语句读取的数据,不适用于写入的数据(包括 INSERT)。

  • 支持的数据格式:

    • 用于托管表和外部表的 Delta 和 Parquet。
    • 使用 Lakehouse Federation 在 Unity 目录中注册的外部表的多种其他数据格式。
  • 策略参数中的常量表达式(字符串、数字、间隔、布尔值、null)。

  • SQL、Python 和 Scala UDF 只要在 Unity Catalog 中注册,即可作为行过滤器或列掩码函数受到支持。 Python 和 Scala UDF 必须包装在 SQL UDF 中。

  • 可以对引用列掩码或行筛选器的表创建视图,但不能向视图添加列掩码或行筛选器。

  • 如果架构与应用于目标表的行筛选器和列掩码兼容,则支持 Delta Lake 更改数据馈送。

  • 支持外表。

  • 支持进行表采样。

  • 当源表、目标表或两者使用行过滤器和列掩码时,支持 MERGE 语句。 这包括具有行筛选器函数(其中包含简单子查询)的表。 以下部分列出了限制。

  • Databricks SQL 具体化视图和 Databricks SQL 流式处理表支持行筛选器和列掩码(公共预览版):

    • 可以向 Databricks SQL 具体化视图或流式处理表中添加行筛选器和列掩码。 定义具体化视图或流式处理表时,必须以声明方式添加掩码。 请参阅创建具体化视图创建流式处理表
    • 可以在包含行筛选器和列掩码的表上定义 Databricks SQL 具体化视图或流式处理表。
  • 在 Lakeflow 声明性管道中声明和发布的物化视图和流表支持行过滤器或列掩码(公共预览版):

    • 可以将行筛选器和列掩码添加到 Lakeflow 声明式管道的物化视图或流式表。
    • 可以在包含行筛选器和列掩码的表上,定义 Lakeflow 声明性管道的物化视图或流表。

    请参阅发布具有行筛选器和列掩码的表

性能建议

行筛选器和列掩码可以确保用户在筛选和屏蔽操作之前无法查看基表值的内容,从而控制数据的可见性。 它们在常见的用例中响应查询时表现良好。 在不太常见的应用程序中,查询引擎必须选择优化查询性能并防止从筛选/掩码值泄露信息,它将始终做出安全决策,但会对查询性能产生一定影响。 若要最大程度地降低此性能影响,请应用以下建议:

  • 使用简单的策略函数: 表达式较少的策略函数通常比更复杂的表达式性能更好。 避免使用映射表和表达式子查询来支持简单的 CASE 函数。
  • 减少函数参数的数目: Azure Databricks 无法优化对策略函数参数生成的源表的列引用,即使查询中未使用这些列。 使用参数较少的策略函数,因为这些表中的查询的性能会更好。
  • 避免添加包含过多 AND 连接符的行筛选器:由于每个表仅支持添加最多一行筛选器,因此一种常见方法是将多个所需策略函数与 AND 合并。 然而,对于每个联结而言,其包含此表其他部分提及的可能影响性能的组件(如映射表)的概率会相应增加。 使用更少的连接来提高性能。
  • 在表策略和来自这些表的查询中,使用不会引发错误的确定性表达式: 如果提供的输入无效(例如 ANSI 除法),某些表达式可能会引发错误。 在这种情况下,SQL 编译器不得在查询计划中向下推那些表达式(如筛选器)的操作太远,以避免在筛选和/或掩码操作之前出现“除以零”等错误,这些错误会泄露有关值的信息。 使用永远不会引发错误的确定性表达式,例如此示例中的 try_divide
  • 通过表运行测试查询以衡量性能:构造实际查询,这些查询表示表所需的工作负荷,其中包含行筛选器和/或列掩码并测量性能。 对策略函数进行小修改并观察其效果,直到在筛选和屏蔽逻辑的性能和表现力之间取得良好平衡。

限制

  • 12.2 LTS 之前的 Databricks Runtime 版本不支持行筛选器或列过滤。 这些运行时安全失败,这意味着如果尝试从这些运行时的不受支持的版本访问表,则不会返回任何数据。
  • 增量共享不适用于行级安全性或列过滤。 但是,可以共享依赖于具有行级别安全性或列掩码的表的数据资产。
  • 不能使用 Iceberg REST 目录或 Unity REST API 访问包含行筛选器或列掩码的表。
  • 不能将行级别安全性或列掩码应用于视图。
  • 按时间顺序查看不适用于行级安全性或列过滤。
  • 不支持对具有策略的表中文件的基于路径的访问。
  • 不支持循环依赖项回到原始策略的行筛选器或列过滤策略。
  • 对具有行级安全性或列掩码的表不支持深度克隆和浅克隆。
  • MERGE 语句不支持包含嵌套、聚合、窗口、限制或非确定性函数的行过滤策略或列过滤策略的表。
  • 不支持 Delta Lake API。

专用访问模式限制

不能从 Databricks Runtime 15.3 或更低版本上的专用访问计算资源访问具有行筛选器或列掩码的表。 如果为无服务器计算启用了工作区,则可以在 Databricks Runtime 15.4 LTS 或更高版本上使用专用访问模式。 但是,在 Databricks Runtime 15.4 到 16.2 上,仅支持读取操作。 写入操作(包括INSERTUPDATEDELETE)需要 DBR 16.3 或更高版本,并且必须使用支持的模式,例如MERGE INTO