创建目录表
到目前为止,我们考虑了从数据帧创建并通过 Delta Lake API 修改的 Delta Lake 表实例。 还可以将 Delta Lake 表定义为 Spark 池的 Hive 元存储中的目录表,并使用 SQL 来进行处理。
外部与托管表
Spark 目录中的表(包括 Delta Lake 表)可以是托管或外部表;了解这类表格之间的区别很重要。
- 托管表是在没有指定位置的情况下定义的,数据文件存储在元存储使用的存储中。 删除表不仅会从目录中删除其元数据,还删除存储其数据文件的文件夹。
- 为自定义文件位置定义外部表,其中存储了表的数据。 表的元数据定义在 Spark 目录中。 删除表会从目录中删除元数据,但不会影响数据文件。
创建目录表
创建目录表有多种方法。
从数据帧创建目录表
可以使用 saveAsTable
操作写入数据帧来创建托管表,如以下示例所示:
# Save a dataframe as a managed table
df.write.format("delta").saveAsTable("MyManagedTable")
## specify a path option to save as an external table
df.write.format("delta").option("path", "/mydata").saveAsTable("MyExternalTable")
使用 SQL 创建目录表
还可以使用含 USING DELTA
子句的 CREATE TABLE
SQL 语句和用于外部表的可选 LOCATION
参数来创建目录表。 可以使用 SparkSQL API 运行语句,如以下示例所示:
spark.sql("CREATE TABLE MyExternalTable USING DELTA LOCATION '/mydata'")
或者,可以使用 Spark 中的本机 SQL 支持运行语句:
%%sql
CREATE TABLE MyExternalTable
USING DELTA
LOCATION '/mydata'
提示
如果目录中已存在具有指定名称的表,则 CREATE TABLE
语句返回错误。 若要规避此行为,可以使用 CREATE TABLE IF NOT EXISTS
语句或 CREATE OR REPLACE TABLE
语句。
定义表架构
到目前为止,所有示例都会创建该表,而无需显式架构。 对于通过写入数据帧创建的表,表架构继承自数据帧。 创建外部表时,架构继承自当前存储在表位置的任何文件。 但是,在创建新的托管表或当前位置为空的外部表时,可以通过指定列名、类型和为 Null 性作为 CREATE TABLE 语句的一部分来定义表架构,如以下示例所示:
%%sql
CREATE TABLE ManagedSalesOrders
(
Orderid INT NOT NULL,
OrderDate TIMESTAMP NOT NULL,
CustomerName STRING,
SalesTotal FLOAT NOT NULL
)
USING DELTA
使用 Delta Lake 时,将强制实施表架构 - 所有插入和更新都必须符合指定的列为 Null 性和数据类型。
使用 DeltaTableBuilder API
可以使用 DeltaTableBuilder API(Delta Lake API 的一部分)来创建目录表,如以下示例所示:
from delta.tables import *
DeltaTable.create(spark) \
.tableName("default.ManagedProducts") \
.addColumn("Productid", "INT") \
.addColumn("ProductName", "STRING") \
.addColumn("Category", "STRING") \
.addColumn("Price", "FLOAT") \
.execute()
与 CREATE TABLE
SQL 语句类似,如果具有指定名称的表已存在,方法 create
将返回错误。 可以通过使用 createIfNotExists
或 createOrReplace
方法来规避此行为。
使用目录表
可以像使用任何基于 SQL 的关系数据库中的表一样使用目录表,通过使用标准 SQL 语句来进行查询和操作。 例如,下面的代码示例使用 SELECT
语句查询 ManagedSalesOrders 表:
%%sql
SELECT orderid, salestotal
FROM ManagedSalesOrders
提示
有关使用 Delta Lake 的详细信息,请参阅 Delta Lake 文档中的表批处理读取和写入。