資料操縱語言 (DML) 和變異是 Spanner 中的兩個 API,可用於修改資料。每個工具都提供類似的資料操作功能。本頁面將比較這兩種方法。
什麼是資料操縱語言 (DML)?
您可以使用 Spanner 中的資料操縱語言 (DML),透過 INSERT
、UPDATE
和 DELETE
陳述式操縱資料庫資料表中的資料。您可以使用用戶端程式庫、Google Cloud 主控台和 gcloud spanner 執行 DML 陳述式。
Spanner 提供以下兩種 DML 執行作業的實作方式,每種方式都有不同的屬性。
標準 DML:適用於標準線上交易處理 (OLTP) 工作負載。
如需詳細資訊 (包括程式碼範例),請參閱「使用 DML」一文。
分區 DML:專為大量更新和刪除而設計,如以下範例所示。
定期清理和垃圾收集。例如刪除舊資料列或將資料欄設為空值。
對具有預設值的新資料欄進行補充作業。例如使用 UPDATE 陳述式,將目前值為空值的新資料欄,設為 False。
如需詳細資訊 (包括程式碼範例),請參閱「使用分區 DML」。
您可以使用批次寫入功能執行大量寫入作業,但不含不需要原子交易的讀取作業。詳情請參閱「使用批次寫入功能修改資料」。
什麼是突變?
變異代表一系列的插入、更新和刪除作業,Spanner 會以不可分割的形式,將這些作業套用到資料庫中不同的資料列和資料表。您可以在變異數中加入適用於不同資料列或不同資料表的運算。定義包含一或多個寫入作業的一或多個變異後,您必須套用變異來提交寫入作業。每項變更都會按照加入變異的順序套用。
如需詳細資訊 (包括程式碼範例),請參閱「使用變異插入、更新與刪除資料」。
DML 和變異的功能比較
下表概略說明 DML 和常見資料庫作業和功能的變異支援。
作業 | DML | 異動 |
---|---|---|
插入資料 | 支援 | 支援 |
刪除資料 | 支援 | 支援 |
更新資料 | 支援 | 支援 |
插入或忽略資料 | 支援 | 不支援 |
讀取自己的寫入作業 (RYW) | 支援 | 不支援 |
插入或更新資料 (Upsert) | 支援 | 支援 |
SQL 語法 | 支援 | 不支援 |
限制檢查 | 每個陳述式後 | 在提交時 |
DML 和突變體支援的功能如下:
讀取寫入內容:讀取有效交易中未提交的結果。使用 DML 陳述式所做的變更,對於相同交易中的後續陳述式而言是可見的。這與使用變異不同,變更必須在交易修訂後才可見。這是因為交易中的變異會在用戶端 (本機) 緩衝,並做為修訂作業的一部分傳送至伺服器。因此,相同交易中的 SQL 或 DML 陳述式無法看到修訂要求中的變異。
檢查限制條件:Spanner 會檢查每個 DML 陳述式之後的限制條件。相較之下,使用變異時,Spanner 會緩衝用戶端的變異直到修訂為止,並在修訂時檢查限制。評估每個 DML 陳述式之後的限制可讓 Spanner 確保在同一筆交易中,後續查詢傳回的資料與結構定義一致。
SQL 語法:DML 提供傳統的資料操縱方式。您可以重複使用 SQL 技巧,透過 DML API 修改資料。
最佳做法:避免在同一筆交易中混用 DML 和變異
如果交易的修訂要求中同時包含 DML 陳述式和變異,Spanner 會先執行 DML 陳述式,然後再執行變異。為避免在用戶端程式庫的程式碼中說明執行順序,您應在單一交易中使用 DML 陳述式或變異,不要兩者並用。
以下 Java 範例說明可能會發生的意外行為。這段程式碼會使用 Mutation API 將兩個資料列插入「Albums」中。程式碼片段接著呼叫 executeUpdate()
來更新新插入的資料列,並呼叫 executeQuery()
來讀取已更新的專輯。
static void updateMarketingBudget(DatabaseClient dbClient) {
dbClient
.readWriteTransaction()
.run(
new TransactionCallable<Void>() {
@Override
public Void run(TransactionContext transaction) throws Exception {
transaction.buffer(
Mutation.newInsertBuilder("Albums")
.set("SingerId")
.to(1)
.set("AlbumId")
.to(1)
.set("AlbumTitle")
.to("Total Junk")
.set("MarketingBudget")
.to(800)
.build());
transaction.buffer(
Mutation.newInsertBuilder("Albums")
.set("SingerId")
.to(1)
.set("AlbumId")
.to(2)
.set("AlbumTitle")
.to("Go Go Go")
.set("MarketingBudget")
.to(200)
.build());
// This UPDATE will not include the Albums inserted above.
String sql =
"UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
+ " WHERE SingerId = 1";
long rowCount = transaction.executeUpdate(Statement.of(sql));
System.out.printf("%d records updated.\n", rowCount);
// Read a newly updated record.
sql =
"SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
+ " WHERE SingerId = 1 AND MarketingBudget < 1000";
ResultSet resultSet =
transaction.executeQuery(Statement.of(sql));
while (resultSet.next()) {
System.out.printf(
"%s %s\n",
resultSet.getString("FirstName"),
resultSet.getString("LastName"));
}
return null;
}
});
}
如果執行這段程式碼,您會看到更新 0 筆記錄。這是因為這是因為使用變異所做的變更,在交易修訂前不會顯示在後續陳述式中。在理想情況下,我們應等到交易結束時,才將寫入內容放在緩衝區。
後續步驟
瞭解如何使用 DML修改資料。
瞭解如何使用變異修改資料。
如要查看交易的變異數,請參閱「擷取交易的修訂統計資料」。