分區資料操縱語言 (分區 DML) 是專為下列類型的大量更新和刪除作業而設計:
- 定期清理和垃圾收集。例如刪除舊資料列或將資料欄設定為
NULL
。 - 對具有預設值的新資料欄進行補充作業。例如使用
UPDATE
陳述式,將目前值為NULL
的新資料欄,設定為False
。
分區 DML 不適合用於小規模交易處理。如要在幾個資料列上執行陳述式,請使用可識別主鍵的交易 DML。詳情請參閱「使用 DML」。
如果您需要提交大量盲寫作業,但不需要不可分割的交易,可以使用批次寫入大量修改 Spanner 資料表。詳情請參閱「使用批次寫入作業修改資料」。
您可以透過 Spanner 資料庫中的統計資料表,深入瞭解進行中的分區 DML 查詢及其進度。詳情請參閱「Active partitioned DMLs statistics」。
DML 和分區 DML
Spanner 支援兩種 DML 陳述式執行模式:
DML 適用於交易處理。詳情請參閱使用 DML。
分區 DML:將索引鍵空間分區,在分區上以個別較小範圍的交易來執行陳述式,以實現大規模、範圍擴及整個資料庫的作業,降低對並行交易處理的影響。詳情請參閱「使用分區 DML」。
下表重點說明兩種執行模式之間的一些差異。
DML | 分區 DML |
---|---|
可能會鎖定不符合 WHERE 子句的資料列。 |
只會鎖定符合 WHERE 子句的資料列。 |
適用交易大小限制。 | Spanner 會處理交易限制和每次交易的並行限制。 |
陳述式不必為冪等。 | DML 陳述式必須為冪等,才能確保結果一致。 |
交易可包含多個 DML 和 SQL 陳述式。 | 分區交易只能包含一個 DML 陳述式。 |
對於陳述式的複雜度沒有任何限制。 | 陳述式必須可完全分區。 |
您在用戶端程式碼中建立讀寫交易。 | Spanner 會建立交易。 |
可分區和冪等
分區 DML 陳述式執行時,分區中的資料列無法存取其他分區中的資料列,而且您無法選擇 Spanner 建立分區的方式。分區可確保擴充性,但也表示分區 DML 陳述式必須「可完全分區」。也就是說,分區 DML 陳述式必須能以一組陳述式聯集表達,其中每個陳述式都會存取資料表的一個資料列,而且每個陳述式都無法存取其他資料表。舉例來說,DML 陳述式如果可以存取多個資料表或執行自我彙整,則無法進行分區。如果 DML 陳述式無法分區,Spanner 會傳回 BadUsage
錯誤。
下面這些 DML 陳述式可完全分區,因為每個陳述式都能套用到資料表中的單一資料列:
UPDATE Singers SET LastName = NULL WHERE LastName = '';
DELETE FROM Albums WHERE MarketingBudget > 10000;
下面這個 DML 陳述式無法完全分區,因為它可存取多個資料表:
# Not fully partitionable
DELETE FROM Singers WHERE
SingerId NOT IN (SELECT SingerId FROM Concerts);
Spanner 可能會因為網路層級的重試要求,對某些分區執行多次分區 DML 陳述式,進而對資料列執行多次陳述式。因此,陳述式必須為「冪等」才能產生一致的結果。如果對單一資料列執行多次陳述式都能獲得相同的結果,則該陳述式為冪等。
下面這個 DML 陳述式為冪等:
UPDATE Singers SET MarketingBudget = 1000 WHERE true;
下面這個 DML 陳述式不是冪等:
UPDATE Singers SET MarketingBudget = 1.5 * MarketingBudget WHERE true;
資料列鎖定
只有在資料列準備要更新或刪除時,Spanner 才會取得鎖定。這個行為與 DML 執行不同,DML 執行可能會在讀取到不符合 WHERE
子句的資料列後進行鎖定。
執行和交易
DML 陳述式是否分區取決於您選擇執行的用戶端程式庫方法。每個用戶端程式庫都會為 DML 執行和分區 DML 執行提供個別的方法。
在呼叫用戶端程式庫方法中,您只能執行一個分區 DML 陳述式。
Spanner 不會將分區 DML 陳述式以不可分割的形式套用到整個資料表。但 Spanner 會將分區 DML 陳述式以不可分割的形式套用到各個分區。
分區 DML 不支援修訂或復原。Spanner 會立即執行並套用 DML 陳述式。
- 如果您取消作業,Spanner 會取消執行中的分區,且不會啟動其餘的分區。Spanner 不會復原任何已經執行的分區。
- 如果執行陳述式導致錯誤,則所有分區上的執行作業都會停止,且 Spanner 會為整個作業傳回錯誤。舉例來說,錯誤包括違反資料類型限制、違反
UNIQUE INDEX
和違反ON DELETE NO ACTION
。視執行失敗的時間點而定,陳述式可能已針對部分資料分割成功執行,但可能從未針對其他資料分割執行。
如果分區 DML 陳述式執行成功,則表示 Spanner 至少已對鍵值範圍的每個分區執行一次陳述式。
已修改的資料列數目
分區 DML 陳述式會傳回有關已修改資料列數目的範圍下限。這可能不是精確的已修改資料列數目,因為系統無法保證 Spanner 是否會計算所有已修改的資料列。
交易限制
Spanner 會建立執行分區 DML 陳述式所需的分區和交易,交易具有限制,每次交易也有並行限制,但 Spanner 會嘗試將交易保持在限制之內。
Spanner 允許每個資料庫最多擁有 20,000 個並行分區 DML 陳述式。
不支援的功能
Spanner 不支援分區 DML 的某些功能:
- 不支援
INSERT
。 - Google Cloud 控制台:您無法在Google Cloud 控制台中執行分區 DML 陳述式。
- 查詢計畫和剖析:Google Cloud CLI 和用戶端程式庫不支援查詢計畫和剖析。
- 從其他資料表或同一資料表的不同資料列讀取資料的子查詢。
如果是複雜情境,例如移動資料表,或需要跨資料表聯結的轉換,請考慮使用 Dataflow 連接器。
範例
以下程式碼範例會更新 Albums
資料表的 MarketingBudget
資料欄。
C++
使用 ExecutePartitionedDml()
函式執行分區 DML 陳述式。
C#
使用 ExecutePartitionedUpdateAsync()
方法執行分區 DML 陳述式。
Go
使用 PartitionedUpdate()
方法執行分區 DML 陳述式。
Java
使用 executePartitionedUpdate()
方法執行分區 DML 陳述式。
Node.js
使用 runPartitionedUpdate()
方法執行分區 DML 陳述式。
PHP
使用 executePartitionedUpdate()
方法執行分區 DML 陳述式。
Python
使用 execute_partitioned_dml()
方法執行分區 DML 陳述式。
Ruby
使用 execute_partitioned_update()
方法執行分區 DML 陳述式。
以下程式碼範例會依據 SingerId
資料欄,從 Singers
資料表刪除列。
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
後續步驟
瞭解如何使用 DML 修改資料。
如要瞭解 DML 和變異之間的差異,請參閱「比較 DML 和變異」
建議您使用 Dataflow 連接器處理其他資料轉換情境。