這很重要
這項功能目前處於 公開預覽版。
Delta Lake 支援生成欄,這是一種特殊類型的欄位,其值會以使用者指定的函數,根據 Delta 資料表中的其他欄位自動產生。 當您寫入具有所產生數據行的數據表,且未明確提供這些數據行的值時,Delta Lake 會自動計算這些值。 例如,您可以從時間戳數據行自動產生日期資料列(用於依日期分割資料表):任何寫入數據表只需要指定時間戳數據行的數據。 不過,如果您明確提供這些值,這些值必須滿足 條件約束(<value> <=> <generation expression>) IS TRUE ,否則寫入將會失敗併發生錯誤。
這很重要
使用產生的數據行建立的數據表具有比預設值更高的數據表寫入器通訊協定版本。 請參閱 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 資料表上宣告識別欄位會停用並行交易。 只有在不需要同時寫入目標數據表的情況下,才使用識別數據行。
Delta Lake 識別數據行是一種產生的數據行類型,可為每個插入數據表的記錄指派唯一值。 下列範例示範在建立數據表語句期間宣告識別數據行的基本語法:
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 (id, event_date, some_value)
SELECT id, event_date, some_value FROM old_table;
-- Insert records and generate new IDs
INSERT INTO new_table (event_date, some_value)
SELECT event_date, some_value FROM new_records;
身份欄限制
使用識別資料列時,存在下列限制:
- 已啟用識別數據行的數據表不支援並行交易。
- 您無法依身份欄分割資料表。
- 您無法使用
ALTER TABLE、ADD、REPLACE或CHANGE識別欄位。 - 您不可更新現有記錄的標識欄的值。
備註
若要變更 IDENTITY 現有記錄的值,您必須刪除記錄,並將 INSERT 它刪除為新記錄。