結構定義更新

Cloud Spanner 讓您無須停機即可更新結構定義。您可透過下列幾種方式更新現有資料庫的結構定義:

支援的結構定義更新

Cloud Spanner 支援下列現有資料庫的結構定義更新:

  • 建立新資料表。新資料表中的資料欄可以是 NOT NULL
  • 刪除資料表,前提是資料表中沒有其他交錯的資料表,而且沒有次要索引。
  • 新增非鍵資料欄到任何資料表。新的非鍵資料欄不得為 NOT NULL
  • 新增 NOT NULL 到非鍵資料欄。
  • 從非鍵資料欄移除 NOT NULL
  • 從任何資料表中捨棄非鍵資料欄,除非有次要索引使用該非鍵資料欄。
  • STRING 資料欄變更為 BYTES 資料欄,或將 BYTES 資料欄變更為 STRING 資料欄。
  • 增加或減少 STRINGBYTES 類型的長度限制 (包括設成 MAX),除非資料欄是主鍵資料欄,且有一個或多個子資料表。
  • 啟用或停用值和主鍵資料欄中的修訂時間戳記
  • 新增或移除任何次要索引。

結構定義更新效能

在 Cloud Spanner 中更新結構定義不需要停機。當您向 Cloud Spanner 資料庫發出一批 DDL 陳述式時,您可以在 Cloud Spanner 透過長時間執行的作業套用更新時,繼續不間斷地從資料庫進行寫入和讀取作業。

執行 DDL 陳述式所需的時間取決於更新是否需要驗證現有的資料,或補充任何資料。舉例來說,如果您將 NOT NULL 註解新增至現有的資料欄,Cloud Spanner 必須讀取資料欄中的所有值,以確認資料欄不包含任何 NULL 值。如果有很多資料需要驗證,這個步驟可能需要花費較長的時間。另一個範例是,如果您將索引新增至資料庫:Cloud Spanner 會使用現有的資料來補充索引。根據索引的定義和對應的主資料表的大小,這個程序可能需要較長的時間。不過,如果您是新增資料欄到資料表,就沒有現有的資料可以驗證,因此 Cloud Spanner 能更迅速地進行更新。

簡單來說,不需要 Cloud Spanner 驗證現有資料的結構定義更新只需要幾分鐘。需要進行驗證的結構定義更新則需要較長的時間,時間長短取決於需要驗證的現有資料量。資料驗證能以較實際工作環境流量低的優先順序在背景中執行。下節將詳細探討需要進行資料驗證的結構定義更新。

需要驗證資料的結構定義更新

您可以將結構定義更新設定為需要驗證現有資料符合新限制後才能完成。當結構定義更新需要驗證資料時,Cloud Spanner 不允許在受影響的結構定義有相衝突的結構定義更新,並且會在背景中驗證資料。如果驗證成功,結構定義更新就會成功。如果驗證失敗,結構定義更新就會失敗。驗證作業是透過長時間執行的作業執行。您可以檢查這些作業的狀態,以判定作業成功或失敗。

舉例來說,假設您在結構定義中定義了 Songwriters 資料表:

CREATE TABLE Songwriters (
  Id         INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  Nickname   STRING(MAX),
  OpaqueData BYTES(MAX),
) PRIMARY KEY (Id);

系統會允許下列結構定義更新,但這些更新需要進行驗證。根據現有的資料量,可能需要較長的時間才能完成驗證:

  • NOT NULL 註解新增至非鍵資料欄。

    範例:ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL

  • 縮減資料欄的長度。

    範例:ALTER TABLE Songwriters ALTER COLUMN FirstName STRING(10)

  • BYTES 變更為 STRING

    範例:ALTER TABLE Songwriters ALTER COLUMN OpaqueData STRING(MAX)

  • 在現有的 TIMESTAMP 資料欄上啟用修訂時間戳記

    範例:ALTER TABLE Albums ALTER COLUMN LastUpdateTime SET OPTIONS (allow_commit_timestamp = true)

如果基礎資料不符合新限制,這些結構定義更新就會失敗。舉例來說,如果 Nickname 資料欄中的任何值為 NULL,上方的 ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL 陳述式會失敗,因為現有資料不符合新定義的 NOT NULL 限制。

資料驗證可能需要幾分鐘到幾小時的時間。完成資料驗證的時間取決於下列因素:

  • 資料集的大小
  • 執行個體中的節點數
  • 執行個體的負載

結構定義更新完成之前,有些結構定義更新可能會變更傳送要求到資料庫的行為。舉例來說,如果您將 NOT NULL 新增到資料欄,Cloud Spanner 會立即開始拒絕在資料欄寫入 NULL 的新要求。如果新結構定義更新最終因資料驗證而失敗,則會有一段封鎖寫入作業的時間,即使舊結構定義可接受這種寫入也是如此。

您可以使用 projects.instances.databases.operations.cancel 方法或使用 gcloud spanner operations,取消長時間執行的資料驗證作業。

批次陳述式的執行順序

如果您是使用 gcloud 工具、REST API 或遠端程序呼叫 (RPC) API,則可發出一批 CREATEALTERDROP 陳述式,其中包含一或多個陳述式。

Cloud Spanner 會依序套用來自同一批次的陳述式,並在發生第一個錯誤時停止。如果套用某個陳述式導致發生錯誤,則會復原該陳述式。系統不會復原批次中之前套用的陳述式的結果。

Cloud Spanner 可能會結合並重新排序來自不同批次的陳述式,且可能會將來自不同批次的陳述式混合成一個不可分割的變更,再套用至資料庫。在每個不可分割的變更中,來自不同批次的陳述式會以任意順序執行。舉例來說,如果某一批陳述式包含 ALTER TABLE MyTable ALTER COLUMN MyColumn STRING(50),而另一批陳述式包含 ALTER TABLE MyTable ALTER COLUMN MyColumn STRING(20),Cloud Spanner 會將該資料欄保留為兩種狀態的其中一種狀態,但不會指明是哪一種。

在結構定義更新期間建立的結構定義版本

Cloud Spanner 使用結構定義版本管理,因此對大型資料庫進行結構定義更新期間無須停機。Cloud Spanner 會維護較舊的結構定義版本,以在處理結構定義更新時支援讀取作業。接著,Cloud Spanner 會建立一或多個新的結構定義版本,以處理結構定義更新。如上所述,每個版本都會在單一不可分割的變更中包含陳述式集合的結果。結構定義版本未必會以一對一的方式對應到其中一批 DDL 陳述式或個別 DDL 陳述式。某些個別 DDL 陳述式 (例如非交錯索引建立,或需要資料驗證的陳述式) 會導致多個結構定義版本。在其他情況下,可在單一版本中將多個 DDL 陳述式組成批次。結構定義版本會耗用大量伺服器和儲存空間資源,持續最多一週的時間。

下表顯示結構定義更新作業的持續時間。

結構定義作業 預估持續時間
CREATE TABLE 數分鐘
CREATE INDEX

數分鐘到數小時,前提是索引為非交錯索引。建立索引需要較長的時間,即使是對小型或空白資料表建立索引也是如此。

數分鐘,前提是索引為交錯索引,並與主資料表的 CREATE TABLE 同時執行。

DROP TABLE 數分鐘
DROP INDEX 數分鐘
ALTER TABLE ... ADD COLUMN 數分鐘
ALTER TABLE ... ALTER COLUMN

數小時,前提是需要背景驗證

數分鐘,前提是不需要背景驗證。

ALTER TABLE ... DROP COLUMN 數分鐘

結構定義更新的最佳做法

下列各節將說明更新結構定義的最佳做法。

發出結構定義更新前的程序

在您發出結構定義更新之前:

  • 針對您要變更的資料庫,驗證其中所有現有資料都符合結構定義更新施加的限制。由於某些類型的結構定義更新能否成功不僅取決於目前的結構定義,更取決於資料庫中的資料,因此即使在測試資料庫結構定義更新獲得成功,並不能保證實際工作環境資料庫結構定義更新會成功。以下是一些常見的範例:
    • 如果您要在現有的資料欄新增 NOT NULL 註解,請檢查資料欄未包含任何現有的 NULL 值。
    • 如果您縮短允許的 STRINGBYTES 資料欄長度,請檢查該資料欄中所有現有的值都符合需要的長度限制。
  • 如果您寫入的資料欄、資料表或索引要經過結構定義更新,請確保寫入的值符合新限制。
  • 如果您要捨棄資料欄、資料表或索引,請確認您目前沒有寫入或讀取該資料欄。

限制 7 天內的結構定義更新數量

請避免在連續 7 天內,對單一資料庫的結構定義進行許多結構定義更新。延長兩次結構定義更新之間的時間,可讓 Cloud Spanner 在建立新版前,移除舊版結構定義。

  • 某些關聯資料庫管理系統有一些軟體套件,會在每個實際工作環境部署上,對資料庫結構定義更新進行一長串的升級和降級。我們不建議在 Cloud Spanner 使用這類程序。
  • Cloud Spanner 經過最佳化,可使用主鍵分割資料以用於多租戶架構解決方案。 多租戶架構解決方案針對每個客戶使用個別資料表,因此造成大量待處理的結構定義更新作業,需要很長時間才能完成這些作業。

請避免在 7 天內執行超過 30 個需要驗證或索引補充作業的 DDL 陳述式,因為每個陳述式都會在內部建立多個結構定義版本。

大型結構定義更新的選項

如果您要建立具有大量索引的資料庫,尤其是要建立非交錯索引,請使用下列其中一種方法:

  • 在資料庫建立要求中建立資料庫及其結構定義。 在建立資料庫時建立資料表和索引十分快速,因為 Cloud Spanner 不需要驗證資料、儲存多個結構定義版本,或與並行交易協調結構定義變更。
  • 建立資料庫,然後以平均每天 3 個的頻率新增索引。

如果結構定義更新包含大量 DDL 陳述式,請勿使用 projects.instances.databases.updateDdl (REST API) 或 UpdateDatabaseDdl (遠端程序呼叫 (RPC) API) 要求一次執行數個陳述式。請將這些陳述式組成較大組的批次。您可批次處理單一要求中的數千個 DDL 陳述式,但只有少於 10 個的陳述式可要求執行驗證或補充作業。驗證和補充作業受限於 Cloud Spanner 結合陳述式的能力,與 Cloud Spanner 建立的結構定義版本數量。即使您使用了批次,也請將新增索引的數量限制為每天大約 3 個索引。

等候 API 要求完成

提出 projects.instances.databases.updateDdl (REST API) 或 UpdateDatabaseDdl (遠端程序呼叫 (RPC) API) 要求時,請分別使用 projects.instances.databases.operations.get (REST API) 或 GetOperation (遠端程序呼叫 (RPC) API),待每個要求完成後,再開始新的要求,讓應用程式追蹤結構定義更新的進度,並將擱置中的結構定義更新的待處理工作維持在可管理的大小。

大量載入

如果您在建立資料後會將資料大量載入到資料表,通常在載入資料後建立索引會比較有效率。如要新增多個索引,使用初始結構定義中的所有資料表和索引來建立資料庫可能會比較有效率,詳情請參閱大型結構定義更新的選項一節。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Cloud Spanner 說明文件