Delta Lake 產生的資料行
重要
這項功能處於公開預覽狀態。
Delta Lake 支援產生的資料行,這些資料行是一種特殊類型的資料行,其值根據使用者指定的函數在 Delta 資料表中的其他資料行上自動產生。 當您寫入具有所產生資料行的資料表且未明確為其提供值時,Delta Lake 會自動計算這些值。 例如,您可以從時間戳記資料行自動產生日期資料行 (用於依日期分割資料表);對資料表進行的任何寫入都僅需為時間戳記資料行指定資料。 但是,如果您明確為這些資料表提供值,則這些值必須滿足條件約束 (<value> <=> <generation expression>) IS TRUE
,否則寫入將失敗並出現錯誤。
重要
使用產生的資料行建立的資料表具有比預設值更高的資料表寫入器通訊協定版本。 請參閱 Azure Databricks 如何管理 Delta Lake 功能相容性?,以了解資料表通訊協定版本控制,以及具有更高版本的資料表通訊協定版本意味著什麼。
建立具有所產生資料行的資料表
下列範例示範如何建立具有所產生資料行的資料表:
SQL
CREATE TABLE default.people10m (
id INT,
firstName STRING,
middleName STRING,
lastName STRING,
gender STRING,
birthDate TIMESTAMP,
dateOfBirth DATE GENERATED ALWAYS AS (CAST(birthDate AS DATE)),
ssn STRING,
salary INT
)
Python
DeltaTable.create(spark) \
.tableName("default.people10m") \
.addColumn("id", "INT") \
.addColumn("firstName", "STRING") \
.addColumn("middleName", "STRING") \
.addColumn("lastName", "STRING", comment = "surname") \
.addColumn("gender", "STRING") \
.addColumn("birthDate", "TIMESTAMP") \
.addColumn("dateOfBirth", DateType(), generatedAlwaysAs="CAST(birthDate AS DATE)") \
.addColumn("ssn", "STRING") \
.addColumn("salary", "INT") \
.execute()
Scala
DeltaTable.create(spark)
.tableName("default.people10m")
.addColumn("id", "INT")
.addColumn("firstName", "STRING")
.addColumn("middleName", "STRING")
.addColumn(
DeltaTable.columnBuilder("lastName")
.dataType("STRING")
.comment("surname")
.build())
.addColumn("lastName", "STRING", comment = "surname")
.addColumn("gender", "STRING")
.addColumn("birthDate", "TIMESTAMP")
.addColumn(
DeltaTable.columnBuilder("dateOfBirth")
.dataType(DateType)
.generatedAlwaysAs("CAST(dateOfBirth AS DATE)")
.build())
.addColumn("ssn", "STRING")
.addColumn("salary", "INT")
.execute()
產生的資料行像普通資料行一樣儲存。 也就是說,它們會佔用儲存空間。
下列限制適用於產生的資料行:
- 產生運算式可以使用 Spark 中的任何 SQL 函數,這些函數在指定相同的引數值時一律傳回相同的結果,但下列類型的函數除外:
- 使用者定義函式。
- 彙總函式。
- 視窗函數。
- 傳回多個資料列的函數。
每當下列其中一個運算式定義了分割資料行時,Delta Lake 就可以為查詢產生分割篩選器:
注意
Databricks Runtime 10.4 LTS 和更低版本中需要 Photon。 Databricks Runtime 11.3 LTS 和更新版本中不需要 Photon。
CAST(col AS DATE)
,col
的類型為TIMESTAMP
。YEAR(col)
,col
的類型為TIMESTAMP
。- 由
YEAR(col), MONTH(col)
定義的兩個分割資料行,col
的類型為TIMESTAMP
。 - 由
YEAR(col), MONTH(col), DAY(col)
定義的三個分割資料行,col
的類型為TIMESTAMP
。 - 由
YEAR(col), MONTH(col), DAY(col), HOUR(col)
定義的四個分割資料行,col
的類型為TIMESTAMP
。 SUBSTRING(col, pos, len)
,col
的類型為STRING
DATE_FORMAT(col, format)
,col
的類型為TIMESTAMP
。- 您只能將日期格式與下列模式搭配使用:
yyyy-MM
和yyyy-MM-dd-HH
。 - 在 Databricks Runtime 10.4 LTS 和更新版本中,您也可以使用下列模式:
yyyy-MM-dd
。
- 您只能將日期格式與下列模式搭配使用:
如果上述其中一個運算式定義了分割資料行,並且查詢使用產生運算式的基礎基底資料行篩選資料,則 Delta Lake 會查看基礎資料行與產生的資料行之間的關係,並在可能的情況下根據產生的分割資料行填入分割篩選器。 例如,假設有下列資料表:
CREATE TABLE events(
eventId BIGINT,
data STRING,
eventType STRING,
eventTime TIMESTAMP,
eventDate date GENERATED ALWAYS AS (CAST(eventTime AS DATE))
)
PARTITIONED BY (eventType, eventDate)
如果您然後執行下列查詢:
SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" <= "2020-10-01 12:00:00"
Delta Lake 會自動產生一個分割篩選器,因此,即使未指定分割篩選器,上述查詢也僅讀取分割 date=2020-10-01
中的資料。
另舉一例,假設提供了下表:
CREATE TABLE events(
eventId BIGINT,
data STRING,
eventType STRING,
eventTime TIMESTAMP,
year INT GENERATED ALWAYS AS (YEAR(eventTime)),
month INT GENERATED ALWAYS AS (MONTH(eventTime)),
day INT GENERATED ALWAYS AS (DAY(eventTime))
)
PARTITIONED BY (eventType, year, month, day)
如果您然後執行下列查詢:
SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" <= "2020-10-01 12:00:00"
Delta Lake 會自動產生一個分割篩選器,因此,即使未指定分割篩選器,上述查詢也僅讀取分割 year=2020/month=10/day=01
中的資料。
您可以使用 EXPLAIN 子句並檢查提供的計畫,以查看 Delta Lake 是否自動產生任何分割篩選器。
在 Delta Lake 中使用識別資料行
重要
在差異資料表上宣告識別資料行會停用並行交易。 僅在不需要對目標資料表進行並行寫入的使用案例中使用識別資料行。
Delta Lake 識別資料行是一種產生的資料行,將為插入到資料表中的每個記錄指派唯一值。 下列範例顯示在 create table 陳述式期間宣告識別資料行的基本語法:
SQL
CREATE TABLE table_name (
id_col1 BIGINT GENERATED ALWAYS AS IDENTITY,
id_col2 BIGINT GENERATED ALWAYS AS IDENTITY (START WITH -1 INCREMENT BY 1),
id_col3 BIGINT GENERATED BY DEFAULT AS IDENTITY,
id_col4 BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH -1 INCREMENT BY 1)
)
Python
from delta.tables import DeltaTable, IdentityGenerator
from pyspark.sql.types import LongType
DeltaTable.create()
.tableName("table_name")
.addColumn("id_col1", dataType=LongType(), generatedAlwaysAs=IdentityGenerator())
.addColumn("id_col2", dataType=LongType(), generatedAlwaysAs=IdentityGenerator(start=-1, step=1))
.addColumn("id_col3", dataType=LongType(), generatedByDefaultAs=IdentityGenerator())
.addColumn("id_col4", dataType=LongType(), generatedByDefaultAs=IdentityGenerator(start=-1, step=1))
.execute()
Scala
import io.delta.tables.DeltaTable
import org.apache.spark.sql.types.LongType
DeltaTable.create(spark)
.tableName("table_name")
.addColumn(
DeltaTable.columnBuilder(spark, "id_col1")
.dataType(LongType)
.generatedAlwaysAsIdentity().build())
.addColumn(
DeltaTable.columnBuilder(spark, "id_col2")
.dataType(LongType)
.generatedAlwaysAsIdentity(start = -1L, step = 1L).build())
.addColumn(
DeltaTable.columnBuilder(spark, "id_col3")
.dataType(LongType)
.generatedByDefaultAsIdentity().build())
.addColumn(
DeltaTable.columnBuilder(spark, "id_col4")
.dataType(LongType)
.generatedByDefaultAsIdentity(start = -1L, step = 1L).build())
.execute()
注意
適用於身分識別數據行的 Scala 和 Python API 可在 Databricks Runtime 16.0 和更新版本中使用。
若要查看使用識別數據行建立數據表的所有 SQL 語法選項,請參閱 CREATE TABLE [USING]。
您可以選擇性地指定下列內容:
- 起始值。
- 步長大小,可以是正值或負值。
起始值與步驟大小預設為 1
。 您無法指定 的步驟大小 0
。
識別資料行指派的值是唯一的,朝指定步長的方向按指定步長大小的倍數遞增,但不保證是連續的。 例如,如果起始值為 0
,步長為 2
,則所有值都是正偶數,但有些偶數可能會略過。
使用子句 GENERATED BY DEFAULT AS IDENTITY
時,插入作業可以為識別資料行指定值。 將此子句修改為 GENERATED ALWAYS AS IDENTITY
,以覆寫手動設定值的功能。
識別資料行僅支援 BIGINT
類型,如果指派的值超過 BIGINT
支援的範圍,則作業會失敗。
若要瞭解如何同步處理識別列值與資料,請參閱 ALTER TABLE ...COLUMN 子句。
CTAS 和識別資料行
在使用 CREATE TABLE table_name AS SELECT
(CTAS) 陳述式時,您無法定義結構描述、識別資料行條件約束或任何其他資料表規格。
若要建立具有識別資料行的新資料表,並填入現有的資料,請執行下列操作:
- 建立具有正確結構描述的資料表,包括識別資料行定義及其他資料表屬性。
- 執行
INSERT
作業。
下列範例使用 DEFAULT
關鍵字來定義識別資料行。 如果插入到資料表中的資料包含識別資料行的有效值,則會使用這些值。
CREATE OR REPLACE TABLE new_table (
id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 5),
event_date DATE,
some_value BIGINT
);
-- Inserts records including existing IDs
INSERT INTO new_table
SELECT id, event_date, some_value FROM old_table;
-- Insert records and generate new IDs
INSERT INTO new_table
SELECT event_date, some_value FROM new_records;
識別資料行限制
使用識別資料行時,存在下列限制:
- 已啟用識別資料行的資料表不支援並行交易。
- 您無法依識別資料行分割資料表。
- 您無法使用
ALTER TABLE
來ADD
、REPLACE
或CHANGE
識別資料行。 - 您無法更新現有記錄的識別資料行的值。
注意
若要變更現有記錄的 IDENTITY
值,您必須刪除記錄,並將其 INSERT
為新記錄。