Azure Synapse Analytics 共享元数据表

通过 Azure Synapse Analytics,不同的工作区计算引擎可在其 Apache Spark 池与无服务器 SQL 池之间共享数据库和表。

Spark 作业创建数据库后,你可通过 Spark 在其中创建使用 Parquet、Delta 或 CSV 作为存储格式的表。 表名称将转换为小写,并且需要使用小写名进行查询。 这些表将立即可供任何 Azure Synapse 工作区 Spark 池查询。 还可以在任何 Spark 作业中按权限使用这些表。

Spark 创建的表、托管表和外部表还可以使用相同名称在无服务器 SQL 池的相应已同步数据库中以外部表形式提供。 在 SQL 中公开 Spark 表提供了有关表同步的更多详细信息。

由于表以异步方式同步到无服务器 SQL 池,因此这些表略微延迟一会儿才会出现。

管理 Spark 创建的表

使用 Spark 管理 Spark 创建的数据库。 例如,通过无服务器 Apache Spark 池作业删除数据库,通过 Spark 在数据库中创建表。

无法从无服务器 SQL 池修改同步数据库中的对象。

使用 SQL 公开 Spark 表

共享的 Spark 表

Spark 提供两种类型的、由 Azure Synapse 在 SQL 中自动公开的表:

  • 托管表

    Spark 提供多种选项(例如 TEXT、CSV、JSON、JDBC、PARQUET、ORC、HIVE、DELTA 和 LIBSVM),供用户选择如何在托管表中存储数据。 这些文件通常存储在托管表数据所存储到的 warehouse 目录中。

  • 外部表

    Spark 还可让用户通过提供 LOCATION 选项或使用 Hive 格式,来基于现有数据创建外部表。 可以基于各种数据格式(包括 Parquet)创建此类外部表。

Azure Synapse 目前只共享使用 SQL 引擎以 Parquet、DELTA 或 CSV 格式存储其数据的托管 Spark 表和外部 Spark 表。 其他格式支持的表不会自动同步。 你可以在自己的 SQL 数据库中自行显式将此类表作为外部表进行同步,前提是 SQL 引擎支持这些表的基础格式。

注意

目前,无服务器 SQL 池仅完全支持 Parquet 和 CSV 格式。 Spark Delta 表也可在无服务器 SQL 池中使用,但此功能目前以公共预览版提供。 在 Spark 中创建的外部表在专用 SQL 池数据库中不可用。

共享 Spark 表

可共享的托管 Spark 表和外部 Spark 表在 SQL 引擎中作为具有以下属性的外部表公开:

  • SQL 外部表的数据源是表示 Spark 表位置文件夹的数据源。
  • SQL 外部表的文件格式为 Parquet、Delta 或 CSV。
  • SQL 外部表的访问凭据是直通身份验证凭据。

由于所有 Spark 表名称是有效的 SQL 表名称,且所有 Spark 列名称是有效的 SQL 列名称,因此 Spark 表名称和列名称将用于 SQL 外部表。

Spark 表与 Synapse SQL 引擎提供的数据类型不同。 下表将 Spark 表数据类型映射到了 SQL 类型:

Spark 数据类型 SQL 数据类型 注释
LongTypelongbigint bigint Spark:LongType 表示 8 字节带符号整数。
SQL:请参阅 int、bigint、smallint 和 tinyint
BooleanTypeboolean bit (Parquet), varchar(6) (CSV) Spark:Boolean。
SQL请参阅
DecimalTypedecimaldecnumeric decimal Spark:DecimalType 表示任意精度的带符号十进制数。 在内部由 java.math.BigDecimal 提供支持。 BigDecimal 由一个任意精度的非标度整数值和一个 32 位整数标度构成。
SQL:固定精度和小数位数。 使用最大精度时,有效值的范围为 - 10^38 +1 到 10^38 - 1。 decimal 的 ISO 同义词为 dec 和 dec(p,s) 。 numeric 在功能上完全等同于 decimal 。 请参阅 decimal 和 numeric
IntegerTypeIntegerint int Spark:IntegerType 表示 4 字节带符号整数
SQL:请参阅 int、bigint、smallint 和 tinyint
ByteTypeBytetinyint smallint Spark:ByteType 表示 1 字节带符号整数 [-128 到 127],ShortType 表示 2 字节带符号整数 [-32768 到 32767]。
SQL:Tinyint 表示 1 字节带符号整数 [0, 255],smallint 表示 2 字节带符号整数 [-32768, 32767]。 请参阅 int、bigint、smallint 和 tinyint
ShortTypeShortsmallint smallint 同上。
DoubleTypeDouble float Spark:DoubleType 表示 8 字节双精度浮点数。 SQL:请参阅 float 和 real
FloatTypefloatreal real Spark:FloatType 表示 4 字节双精度浮点数。 SQL:请参阅 float 和 real
DateTypedate date Spark:DateType 表示包含年月日字段的值,不带时区
SQL:请参阅 date
TimestampTypetimestamp datetime2 Spark:TimestampType 表示包含年、月、日、小时、分钟和秒字段的值,还包含会话本地时区。 时间戳值表示绝对时间点。
SQL:请参阅 datetime2
char char
StringTypeStringvarchar Varchar(n) Spark:StringType 表示字符串值。 VarcharType(n) 是 StringType 的变体,它有长度限制。 如果输入字符串超过长度限制,数据写入将失败。 此类型只能用于表架构,不能用于函数/运算符。
CharType(n) 是固定长度的 VarcharType(n) 的变体 。 读取 CharType(n) 类型的列会始终返回长度为 n 的字符串值。 CharType(n) 列比较会将较短的列填充到较长的列。
SQL:如果从 Spark 提供了长度,则 varchar(n) 中的 n 将设置为该长度。 如果是已分区的列,则 n 最大可为 2048。 否则,将是 varchar(max)。 请参阅 char 和 varchar
将其与排序规则 Latin1_General_100_BIN2_UTF8 一起使用。
BinaryTypebinary varbinary(n) SQL:如果从 Spark 提供了长度,则 Varbinary(n) 中的 n 将设置为该长度。 如果是已分区的列,则 n 最大可为 2048。 否则,将是 Varbinary(max)。 请参阅 binary 和 varbinary
arraymapstruct varchar(max) SQL:使用排序规则 Latin1_General_100_BIN2_UTF8 序列化为 JSON。 请参阅 JSON 数据

备注

数据库级别排序规则为 Latin1_General_100_CI_AS_SC_UTF8

安全模型

Spark 数据库和表及其在 SQL 引擎中的已同步表示形式将在基础存储级别受到保护。 由于它们当前对对象本身不拥有权限,因此可以在对象资源管理器中查看对象。

创建托管表的安全主体被视为该表的所有者,对该表以及基础文件夹和文件拥有所有权限。 此外,数据库的所有者将自动成为该表的共同所有者。

如果使用直通身份验证创建 Spark 或 SQL 外部表,则数据只会在文件夹和文件级别受到保护。 如果某人查询这种类型的外部表,则该查询提交者的安全标识会传递给文件系统,而文件系统将检查该提交者是否有访问权限。

有关如何设置文件夹和文件权限的详细信息,请参阅 Azure Synapse Analytics 共享数据库

示例

在 Spark 中创建托管表并从无服务器 SQL 池进行查询

在此场景中,你有一个名为 mytestdb 的 Spark 数据库。 请参阅使用无服务器 SQL 池创建并连接到 Spark 数据库

运行以下命令,使用 SparkSQL 创建托管的 Spark 表:

    CREATE TABLE mytestdb.myparquettable(id int, name string, birthdate date) USING Parquet

此命令在数据库 mytestdb 中创建表 myparquettable。 表名称将转换为小写。 在短暂的延迟后,可以在无服务器 SQL 池中看到该表。 例如,在无服务器 SQL 池中运行以下语句。

    USE mytestdb;
    SELECT * FROM sys.tables;

请验证结果中是否包含 myparquettable

备注

不使用 Delta、Parquet 或 CSV 作为存储格式的表不会同步。

接下来,通过 Spark 在该表中插入一些值,例如,在 C# 笔记本中使用以下 C# Spark 语句:

using Microsoft.Spark.Sql.Types;

var data = new List<GenericRow>();

data.Add(new GenericRow(new object[] { 1, "Alice", new Date(2010, 1, 1)}));
data.Add(new GenericRow(new object[] { 2, "Bob", new Date(1990, 1, 1)}));

var schema = new StructType
    (new List<StructField>()
        {
            new StructField("id", new IntegerType()),
            new StructField("name", new StringType()),
            new StructField("birthdate", new DateType())
        }
    );

var df = spark.CreateDataFrame(data, schema);
df.Write().Mode(SaveMode.Append).InsertInto("mytestdb.myparquettable");

现在,可以从无服务器 SQL 池中读取数据,如下所示:

SELECT * FROM mytestdb.myparquettable WHERE name = 'Alice';

在结果中应会看到以下行:

id | name | birthdate
---+-------+-----------
1 | Alice | 2010-01-01

在 Spark 中创建外部表并从无服务器 SQL 池进行查询

在此示例中,我们将基于在前一个托管表示例中创建的 Parquet 数据文件创建一个外部 Spark 表。

例如,使用 SparkSQL 运行:

CREATE TABLE mytestdb.myexternalparquettable
    USING Parquet
    LOCATION "abfss://<storage-name>.dfs.core.chinacloudapi.cn/<fs>/synapse/workspaces/<synapse_ws>/warehouse/mytestdb.db/myparquettable/"

将占位符 <storage-name> 替换为正在使用的 ADLS Gen2 存储帐户名称,<fs> 替换为正在使用的文件系统名称,并将 <synapse_ws> 占位符替换为用于运行此示例的 Azure Synapse 工作区的名称。

以上示例在数据库 mytestdb 中创建表 myextneralparquettable。 在短暂的延迟后,可以在无服务器 SQL 池中看到该表。 例如,在无服务器 SQL 池中运行以下语句。

USE mytestdb;
SELECT * FROM sys.tables;

请验证结果中是否包含 myexternalparquettable

现在,可以从无服务器 SQL 池中读取数据,如下所示:

SELECT * FROM mytestdb.dbo.myexternalparquettable WHERE name = 'Alice';

在结果中应会看到以下行:

id | name | birthdate
---+-------+-----------
1 | Alice | 2010-01-01

后续步骤