外鍵

本文說明 Spanner 中的外部鍵,以及如何使用外部鍵在資料庫中強制執行參照完整性。以下主題可協助您瞭解外鍵和使用方式:

Spanner 中的外鍵總覽

外鍵可定義資料表之間的關係。您可以使用外鍵,確保 Spanner 中這些關係的資料完整性。

假設您是電子商務業務的首席開發人員。您正在設計資料庫,用來處理顧客訂單。資料庫必須儲存每筆訂單、顧客和產品的相關資訊。圖 1 說明應用程式的基本資料庫結構。

訂單處理資料庫的基本結構。

圖 1. 訂單處理資料庫的圖表

您定義了 Customers 資料表來儲存顧客資訊、Orders 資料表來追蹤所有訂單,以及 Products 資料表來儲存每項產品的資訊。

圖 1 也顯示資料表之間的連結,對應下列實際關係:

  • 顧客下單。

  • 訂購產品。

您決定資料庫要強制執行下列規則,確保系統中的訂單有效。

  • 您無法為不存在的顧客建立訂單。

  • 如果沒有販售某項產品,消費者就無法訂購。

強制執行這些規則或限制時,您會維護資料的參照完整性。如果資料庫維護參照完整性,所有新增無效資料的嘗試都會失敗,因為這會導致資料間的連結或參照無效。參照完整性可避免使用者發生錯誤。根據預設,Spanner 會使用外鍵強制執行參照完整性。

使用外鍵定義參考完整性

以下再次檢查訂單處理範例,並在設計中加入更多詳細資料,如圖 2 所示。

含外鍵的資料庫結構定義

圖 2:資料庫結構定義圖,其中包含外部鍵

設計畫面現在會顯示每個資料表中的資料欄名稱和類型。Orders資料表也定義了兩個外鍵關係。「FK_CustomerOrder」預期 Orders 中的所有資料列都有有效的 CustomerIdFK_ProductOrder 外鍵會預期 Orders 資料表中的所有 ProductId 值都有效。下表將這些限制條件對應回您想強制執行的實際規則。

外鍵名稱 限制 實際描述
FK_CustomerOrder 預期 Orders 中的所有資料列都有有效 CustomerId 有效顧客下單
FK_ProductOrder 預期 Orders 中的所有資料列都有有效 ProductId 已訂購有效產品

Spanner 會強制執行使用強制執行的外部索引鍵指定的限制。也就是說,如果交易嘗試在 Orders 資料表中插入或更新資料列,但該資料列的 CustomerIdProductId 未在 CustomersProducts 資料表中找到,Spanner 就會讓交易失敗。如果交易嘗試更新或刪除 CustomersProducts 資料表中的資料列,導致 Orders 資料表中的 ID 無效,交易也會失敗。如要進一步瞭解 Spanner 如何驗證限制,請參閱「交易限制驗證」一節。

與強制執行的外鍵不同,Spanner 不會驗證資訊外鍵的限制。也就是說,如果您在此情境中使用資訊性外鍵,則嘗試在 Orders 資料表中插入或更新含有 CustomerIdProductId 的資料列時,系統不會驗證該資料列,交易也不會失敗。CustomersProducts此外,與強制執行的外部鍵不同,資訊外部鍵僅適用於 GoogleSQL,不適用於 PostgreSQL。

外鍵特性

以下列出 Spanner 外鍵的特徵。

  • 定義外鍵的資料表是參照資料表,而外鍵資料欄則是參照資料欄。

  • 外鍵會參照參照資料表的參照資料欄。

  • 如範例所示,您可以為每個外部鍵限制命名。如果未指定名稱,Spanner 會為您產生名稱。您可以從 Spanner 的 INFORMATION_SCHEMA 查詢產生的名稱。限制名稱的範圍為結構定義,與資料表和索引的名稱相同,且不得與結構定義中的其他名稱重複。

  • 參照和被參照的資料欄數必須相同。順序相當重要。舉例來說,第一個參照欄會參照第一個參照欄,第二個參照欄則會參照第二個參照欄。

  • 參照欄及其參照的對應欄必須屬於相同類型。您必須能夠為資料欄建立索引。

  • 您無法在具有 allow_commit_timestamp=true 選項的資料欄上建立外部鍵。

  • 系統不支援陣列資料欄。

  • 系統不支援 JSON 欄。

  • 外鍵可以參照同一資料表的欄 (自我參照外鍵)。舉例來說,Employee 資料表含有參照資料表 EmployeeId 資料欄的 ManagerId 資料欄。

  • 外鍵也可以在資料表之間形成循環關係,其中兩個資料表會直接或間接參照彼此。建立外鍵前,參照的資料表必須存在。也就是說,至少要使用 ALTER TABLE 陳述式新增一個外鍵。

  • 參照鍵不得重複。如果外鍵的參照資料欄與參照資料表的主鍵資料欄相符,Spanner 會使用參照資料表的 PRIMARY KEY。如果 Spanner 無法使用參照資料表的主鍵,就會在參照資料欄上建立 UNIQUE NULL_FILTERED INDEX

  • 外鍵不會使用您建立的次要索引。而是建立自己的支援索引。支援索引可用於查詢評估,包括明確的 force_index 指令。您可以從 Spanner 的 INFORMATION_SCHEMA 查詢備份索引的名稱。詳情請參閱「支援索引」。

外鍵類型

外鍵分為兩種:強制資訊。強制執行的外鍵是預設值,可強制執行參照完整性。資訊外鍵不會強制執行參照完整性,最適合用來宣告查詢最佳化的預期邏輯資料模型。詳情請參閱下列「強制執行」和「資訊」外鍵章節,以及「外鍵類型比較」表格。

強制執行的外鍵

強制外鍵 (Spanner 中的預設外鍵類型) 會強制執行參照完整性。由於強制執行的外鍵會強制執行參照完整性,因此嘗試執行下列操作時會失敗:

  • 如果參照資料表中的外鍵值在參照資料表中不存在,則無法在參照資料表中新增資料列。

  • 如果參照資料表中的資料列參照了某個資料列,您就無法刪除該資料列。

系統會強制執行所有 PostgreSQL 外鍵。GoogleSQL 外鍵預設為強制執行。由於系統預設會強制執行外鍵,因此您不一定要使用 ENFORCED 關鍵字,指定強制執行 GoogleSQL 外鍵。

資訊外鍵

資訊外鍵用於宣告查詢最佳化的預期邏輯資料模型。雖然參考的資料表鍵必須是資訊外鍵的專屬鍵,但系統不會強制執行參考完整性。如果您想在使用參考完整性資訊外來鍵時,選擇性地驗證參考完整性,則必須在用戶端管理驗證邏輯。詳情請參閱使用資訊性外部鍵

使用 NOT ENFORCED 關鍵字指定 GoogleSQL 外鍵為資訊性外鍵。PostgreSQL 不支援資訊外鍵。

外鍵類型比較

「強制執行」和「僅供參考」都有好處。下列各節將比較這兩種外鍵,並提供一些最佳做法。

高階外鍵差異

大致來說,強制資訊外鍵的差異如下:

  • 違規處置。強制執行的外鍵會驗證並確保寫入作業的參照完整性。資訊外鍵不會驗證或保證參考完整性。

  • 儲存空間。強制執行的外鍵可能需要額外儲存空間,才能在受限資料表上建立支援索引。

  • 寫入處理量。與資訊外鍵相比,強制執行的外鍵在寫入路徑中可能會產生更多額外負擔。

  • 查詢最佳化。這兩種外鍵都可用於查詢最佳化。如果允許最佳化工具使用資訊外鍵,且資料與資訊外鍵關係不符 (例如,某些受限鍵在參照資料表中沒有相符的參照鍵),查詢結果可能無法反映實際資料。

外鍵差異表

下表詳細列出強制執行和參考外鍵之間的差異:

強制執行的外鍵 資訊外鍵
關鍵字 ENFORCED NOT ENFORCED
GoogleSQL 支援 可以。GoogleSQL 預設會強制執行外鍵。 是。
PostgreSQL 支援 可以。PostgreSQL 只能強制執行外部鍵。 不會。
儲存空間 強制執行的外部索引鍵最多需要兩個支援索引的儲存空間。 資訊型外部索引鍵最多需要一個支援索引的儲存空間。
視需要為參照的資料表欄建立支援索引 是。 是。
視需要為參照資料表資料欄建立支援索引 是。 不會。
支援外鍵動作 是。 不會。
驗證及強制執行參照完整性 是。 否。沒有驗證程序可提升寫入效能,但如果資訊性外鍵用於查詢最佳化,可能會影響查詢結果。您可以使用用戶端驗證或強制執行的外鍵,確保參考完整性。

選擇要使用的外鍵類型

您可以參考下列準則,決定要使用的外鍵類型:

建議您先從強制執行的外部鍵著手。強制執行的外部鍵可確保資料和邏輯模型隨時保持一致。除非強制執行的外鍵不適用於您的用途,否則建議使用這個選項。

如果符合下列所有條件,建議您考慮使用資訊性外部鍵:

  • 您想在查詢最佳化中使用資訊外鍵所描述的邏輯資料模型。

  • 維持嚴格的參照完整性不切實際,或會大幅影響效能。以下列舉幾個可考慮使用資訊外鍵的情況:

    • 上游資料來源採用最終一致性模型。在這種情況下,來源系統的更新可能不會立即反映在 Spanner 中。由於更新可能不會立即生效,外來鍵關係可能會出現短暫的不一致。

    • 您的資料包含參照資料列,且這些資料列有大量參照關係。更新這些資料列可能會耗用大量資源,因為 Spanner 必須驗證或 (在某些情況下) 刪除與維護參照完整性相關的所有資料列。在這種情況下,更新可能會影響 Spanner 效能,並減緩並行交易的速度。

  • 應用程式可以處理潛在的資料不一致問題,以及這些問題對查詢結果的影響。

使用資訊外鍵

下列主題僅適用於資訊外鍵。如要瞭解適用於資訊和強制執行的外部鍵主題,請參閱下列內容:

建立含有資訊外鍵的新資料表

您可以使用 DDL 陳述式,在 Spanner 資料庫中建立及移除參考外鍵 。您可以使用 CREATE TABLE 陳述式,將外鍵新增至新資料表。同樣地,您可以使用 ALTER TABLE 陳述式,在現有資料表中新增或移除外來鍵。

下列範例會使用 GoogleSQL 建立具有資訊性外鍵的新資料表。PostgreSQL 不支援資訊外鍵。

GoogleSQL

CREATE TABLE Customers (
  CustomerId INT64 NOT NULL,
  CustomerName STRING(MAX) NOT NULL,
) PRIMARY KEY(CustomerId);

CREATE TABLE Orders (
  OrderId INT64 NOT NULL,
  CustomerId INT64 NOT NULL,
  Quantity INT64 NOT NULL,
  ProductId INT64 NOT NULL,
  CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerId)
   REFERENCES Customers (CustomerId) NOT ENFORCED
 ) PRIMARY KEY (OrderId);

PostgreSQL

Not Supported

如需建立及管理外鍵的更多範例,請參閱「建立及管理外鍵關係」。如要進一步瞭解 DDL 陳述式,請參閱 DDL 參考資料

使用資訊外鍵進行查詢最佳化

查詢最佳化工具可使用強制執行的外部索引鍵資訊外部索引鍵,提升查詢效能。使用資訊外鍵可讓您充分運用最佳化的查詢計畫,不必嚴格執行參照完整性,避免產生額外負擔。

如果啟用查詢最佳化工具來運用參考外鍵資訊,請務必瞭解最佳化作業的正確性,取決於資料是否與參考外鍵所描述的邏輯模型一致。如有不一致的情況,查詢結果可能無法反映實際資料。舉例來說,如果受限資料欄中的值在參照資料欄中沒有相符的值,就會發生不一致的情況。

根據預設,查詢最佳化工具會使用 NOT ENFORCED 外鍵。如要變更這項設定,請將資料庫選項 use_unenforced_foreign_key_for_query_optimization 設為 false。以下是 GoogleSQL 範例,可說明這項功能 (PostgreSQL 不提供資訊性外部鍵):

SET DATABASE OPTIONS (
    use_unenforced_foreign_key_for_query_optimization = false
);

布林值查詢陳述式提示 @{use_unenforced_foreign_key} 會在每個查詢的基礎上,覆寫資料庫選項,控制最佳化工具是否使用 NOT ENFORCED 外鍵。排解查詢結果不如預期的問題時,停用這項提示或資料庫選項可能會有幫助。以下說明如何使用 @{use_unenforced_foreign_key}

@{use_unenforced_foreign_key=false} SELECT Orders.CustomerId
    FROM Orders
    INNER JOIN Customers ON Customers.CustomerId = Orders.CustomerId;

使用強制執行的外鍵

下列主題僅適用於強制執行的外部鍵。如要瞭解適用於資訊和強制執行的外部鍵主題,請參閱下列內容:

建立新資料表並強制執行外鍵

您可以使用 DDL,在 Spanner 資料庫中建立、移除及強制執行外鍵。您可以使用 CREATE TABLE 陳述式,將外鍵新增至新資料表。同樣地,您可以使用 ALTER TABLE 陳述式,在現有資料表中新增或移除外鍵。

您可以使用 DDL,在 Spanner 資料庫中建立及移除外鍵。您可以使用 CREATE TABLE 陳述式,將外鍵新增至新資料表。同樣地,您可以使用 ALTER TABLE 陳述式,在現有資料表中新增或移除外鍵。

以下範例說明如何建立新資料表,並強制執行外鍵。

GoogleSQL

CREATE TABLE Customers (
CustomerId INT64 NOT NULL,
CustomerName STRING(MAX) NOT NULL,
) PRIMARY KEY(CustomerId);

CREATE TABLE Orders (
OrderId INT64 NOT NULL,
CustomerId INT64 NOT NULL,
Quantity INT64 NOT NULL,
ProductId INT64 NOT NULL,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerId)
  REFERENCES Customers (CustomerId) ENFORCED
) PRIMARY KEY (OrderId);

PostgreSQL

CREATE TABLE Customers (
CustomerId bigint NOT NULL,
CustomerName character varying(1024) NOT NULL,
PRIMARY KEY(CustomerId)
);

CREATE TABLE Orders (
OrderId BIGINT NOT NULL,
CustomerId BIGINT NOT NULL,
Quantity BIGINT NOT NULL,
ProductId BIGINT NOT NULL,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerId)
  REFERENCES Customers (CustomerId),
PRIMARY KEY (OrderId)
);

如需建立及管理外鍵的更多範例,請參閱「建立及管理外鍵關係」。

外鍵動作

外鍵動作只能在強制執行的外鍵上定義。

外鍵動作可控制在參照的資料欄遭到刪除或更新時,受限資料欄會發生什麼情況。Spanner 支援使用 ON DELETE CASCADE 動作。使用外鍵 ON DELETE CASCADE action 時,如果刪除含有參照外鍵的資料列,系統也會在同一筆交易中刪除參照該鍵的所有資料列。

使用 DDL 建立資料庫時,您可以新增含有動作的外鍵。使用 CREATE TABLE 陳述式,將外鍵連同動作新增至新資料表。同樣地,您可以使用 ALTER TABLE 陳述式,將外鍵動作新增至現有資料表,或移除外鍵動作。以下範例說明如何建立含有外鍵動作的新資料表。

GoogleSQL

CREATE TABLE ShoppingCarts (
CartId INT64 NOT NULL,
CustomerId INT64 NOT NULL,
CustomerName STRING(MAX) NOT NULL,
CONSTRAINT FKShoppingCartsCustomers FOREIGN KEY(CustomerId, CustomerName)
  REFERENCES Customers(CustomerId, CustomerName) ON DELETE CASCADE,
) PRIMARY KEY(CartId);

PostgreSQL

CREATE TABLE ShoppingCarts (
CartId bigint NOT NULL,
CustomerId bigint NOT NULL,
CustomerName character varying(1024) NOT NULL,
PRIMARY KEY(CartId),
CONSTRAINT fkshoppingcartscustomers FOREIGN KEY (CustomerId, CustomerName)
  REFERENCES Customers(CustomerId, CustomerName) ON DELETE CASCADE
);

以下列出 Spanner 中外鍵動作的特徵。

  • 外鍵動作為 ON DELETE CASCADEON DELETE NO ACTION

  • 您可以查詢 INFORMATION_SCHEMA,找出有動作的外鍵限制。

  • 系統不支援在現有外鍵限制上新增外鍵動作。您必須新增含有動作的新外鍵限制。

限制驗證

限制驗證僅適用於強制執行的外部鍵。

Spanner 會在交易提交時,或在交易中後續作業可見寫入效果時,驗證強制執行的外鍵限制。

系統會比對插入參照資料欄的值與參照資料表和參照資料欄的值。系統不會檢查參照值的 NULL 資料列,因此您可以將這些資料列新增至參照資料表。

嘗試使用 DML 陳述式或 API 更新資料時,Spanner 會驗證所有適用的強制外鍵參照限制。如有任何限制無效,系統會復原所有待處理的變更。

系統會在每個 DML 陳述式之後立即進行驗證。舉例來說,您必須先插入參照的資料列,才能插入參照該資料列的資料列。使用修改作業 API 時,修改作業會緩衝處理,直到交易提交為止。強制執行的外鍵驗證會延後,直到交易提交為止。在這種情況下,可以先插入參照資料列。

系統會評估每筆交易的修改內容,判斷是否會影響強制執行的外部鍵限制。這些評估作業可能需要向伺服器提出額外要求。後端索引也需要額外的處理時間,才能評估交易修改內容並維護索引。每個索引也需要額外儲存空間。

長時間執行的刪除連鎖動作

從參照資料表刪除資料列時,Spanner 必須刪除參照已刪除資料列的參照資料表中的所有資料列。這可能會導致連鎖效應,單一刪除作業會產生數千個其他刪除作業。在資料表中加入外鍵限制條件並搭配刪除連鎖動作,或建立資料表並搭配刪除連鎖動作,可能會拖慢刪除作業。

外鍵刪除連鎖反應的突變次數超出上限

使用外鍵刪除連鎖刪除大量記錄可能會影響效能。這是因為每筆刪除的記錄都會觸發刪除所有相關記錄。如要使用外鍵刪除連鎖刪除大量記錄,請先從子項資料表明確刪除資料列,再從父項資料表刪除資料列。這樣可避免交易因突變限制而失敗。

強制執行的外鍵與資料表交錯的比較

Spanner 的資料表交錯功能相當適合用於下列情況:有許多父項子項關係,且子項資料表的主鍵包含父項資料表的主鍵欄。將子項資料列與父項資料列存放在相同位置即可大幅提高效能。

外鍵是應用方式較為廣泛的父項子項關係解決方案,可用於更多用途。外鍵並非僅限於主鍵欄,資料表可以同時含有多組外鍵關係,在某些關係中是父項,在其他關係中則是子項。不過,外鍵關係並不代表資料表位於儲存空間層中的相同位置。

請參考以下範例,其中使用定義如下的 Orders 資料表:

含外鍵的資料庫結構定義

圖 3:資料庫結構定義圖 (強制執行外部鍵)

圖 3 中的設計有一些限制。舉例來說,每個訂單只能包含一個訂單項目。

假設顧客希望每筆訂單都能訂購多項產品。您可以導入 OrderItems 表格,其中包含顧客訂購的每項產品,藉此改善設計。您可以導入另一個強制執行的外鍵,代表 OrdersOrderItems 之間的新一對多關係。不過,您也知道自己經常需要對訂單及其各自的訂單項目執行查詢。由於這類資料的共置作業可提升效能,您會想使用 Spanner 的資料表交錯功能建立父項與子項關係。

以下說明如何定義 OrderItems 資料表,並與 Orders 交錯。

GoogleSQL

CREATE TABLE Products (
ProductId INT64 NOT NULL,
Name STRING(256) NOT NULL,
Price FLOAT64
) PRIMARY KEY(ProductId);

CREATE TABLE OrderItems (
OrderId INT64 NOT NULL,
ProductId INT64 NOT NULL,
Quantity INT64 NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products (ProductId)
) PRIMARY KEY (OrderId, ProductId),
INTERLEAVE IN PARENT Orders ON DELETE CASCADE;

PostgreSQL

CREATE TABLE Products (
ProductId BIGINT NOT NULL,
Name varchar(256) NOT NULL,
Price float8,
PRIMARY KEY(ProductId)
);

CREATE TABLE OrderItems (
OrderId BIGINT NOT NULL,
ProductId BIGINT NOT NULL,
Quantity BIGINT NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products (ProductId),
PRIMARY KEY (OrderId, ProductId)
) INTERLEAVE IN PARENT Orders ON DELETE CASCADE;

圖 4 是更新後資料庫結構定義的視覺化呈現結果,因為導入了這個新資料表 OrderItems,並與 Orders 交錯。您也可以在這裡查看這兩個資料表之間的一對多關係。

資料庫結構定義:顯示「訂單」和新的交錯式「訂購商品」資料表之間的一對多關係

圖 4:新增交錯的 OrderItems 資料表

在這個設定中,每個訂單可以有多個 OrderItems 項目,且每個訂單的 OrderItems 項目會交錯排列,因此與訂單位於相同位置。以這種方式實體交錯 OrdersOrderItems,可提升效能、有效地預先彙整資料表、讓您一併存取相關資料列,同時減少磁碟存取次數。舉例來說,Spanner 可利用主鍵在本機進行彙整,減少存取磁碟的次數並降低網路流量。

如果交易中的變異數超過 80,000,交易就會失敗。這類大型連鎖刪除作業適用於具有「交錯於父項」關係的資料表,但不適用於具有外鍵關係的資料表。如果您有外鍵關係,且需要刪除大量資料列,請務必先從子項表格中明確刪除資料列。

如果您有一個使用者資料表,與另一個資料表有外鍵關係,且從參照資料表刪除資料列會觸發數百萬個資料列的刪除作業,則應使用「交錯於父項」的刪除連鎖作業設計結構定義。

比較表

下表摘要比較了強制執行的外鍵和資料表交錯。您可以根據這項資訊,決定適合設計的項目。

父項/子項關係類型 資料表交錯 強制執行的外鍵
可以使用主鍵
可以使用非主鍵欄
支援的父項人數 0 .. 1 0 .. N
將父項和子項資料儲存在一起
支援串連刪除
比對模式為空值 如果所有參照值與參照值不相異,則通過驗證。
空值與空值不相異,空值與非空值相異。
如果任何參照值為空值,則通過驗證。
如果所有參照值皆為非空值,且參照的表格含有值與參照值相等的資料列,則通過驗證。
如果找不到相符的資料列,則驗證失敗。
違規處置時間 使用修改作業 API 時,每項作業的費用。
使用 DML 時,以陳述式為單位。
使用變動 API 時,每筆交易的費用。
使用 DML 時,以陳述式為單位。
可移除 不可以。建立資料表交錯後,除非刪除整個子項資料表,否則無法移除。

支援索引

外鍵不會使用使用者建立的索引。而是建立自己的支援索引。強制資訊外鍵在 Spanner 中建立支援索引的方式不同:

  • 如果是強制執行的外鍵,Spanner 最多可為每個外鍵建立兩個次要支援索引,一個用於參照資料欄,另一個用於參照資料欄。

  • 如果是參考外鍵,Spanner 可以在需要時為參照的資料欄建立最多一個支援索引。資訊外鍵不會為參照資料欄建立支援索引。

不論是強制執行或資訊外鍵,外鍵通常會參照參照資料表的主鍵,因此通常不需要參照資料表的索引。因此,資訊性外部鍵通常沒有支援索引。如有需要,系統會為參照資料表建立 UNIQUE NULL_FILTERED 索引做為支援索引。如果現有資料違反索引的唯一性限制,就無法建立外鍵。

資訊外鍵沒有參照資料表的支援索引。如果是強制執行的外部索引鍵,參照資料表的支援索引為 NULL_FILTERED

如果兩個以上的外部鍵需要相同的支援索引,Spanner 會為每個外部鍵建立單一索引。當使用這些索引的外鍵遭到捨棄時,支援索引也會一併捨棄。您無法變更或捨棄支援索引。

Spanner 會使用每個資料庫的資訊結構定義,儲存備份索引的中繼資料。INFORMATION_SCHEMA.INDEXES 內的資料列,如果 SPANNER_IS_MANAGED 值為 true,則說明備份索引。

除了直接叫用資訊結構定義的 SQL 查詢外,Google Cloud 主控台不會顯示資料庫後端索引的任何資訊。

長時間執行的結構定義變更

在現有資料表中加入強制執行的外鍵,或建立含有外鍵的新資料表,可能會導致作業長時間執行。如果是新資料表,必須等到長時間執行的作業完成後,才能寫入資料表。

下表說明在新的或現有資料表中,強制執行和資訊外鍵會發生什麼情況:

資料表類型 強制執行的外鍵 資訊外鍵
新增 Spanner 會視需要為每個外鍵回填參照的索引。 Spanner 會視需要為每個外鍵回填參照的索引。
現有 Spanner 會視需要回填參照和參照的索引。Spanner 也會驗證資料表中的現有資料,確保資料符合外鍵的參照完整性限制。如有任何資料無效,結構定義變更就會失敗。 Spanner 會視需要回填參照的索引,且不會驗證資料表中的現有資料。

系統不支援下列項目:

  • 在現有強制執行的外鍵限制中加入外鍵動作。
  • 變更現有外來鍵的強制執行狀態。

在上述兩種情況下,我們建議您改為採取下列做法:

  1. 新增限制,並設定必要動作或強制執行方式。
  2. 捨棄舊的限制。

新增限制並捨棄舊限制,可避免發生長時間執行的 ALTER CONSTRAINT 作業問題。舉例來說,假設您想在現有的外鍵上新增 DELETE CASCADE 動作,使用 ON DELETE CASCADE 動作建立新的外部鍵後,這兩項限制的效果都是 DELETE CASCADE 動作。接著即可安全地捨棄舊限制。

如果索引未用於其他外部索引鍵限制,捨棄限制可能會導致捨棄外部索引鍵支援索引。因此,如果先捨棄舊的限制,之後再新增具有動作的相同外鍵限制,可能會導致長時間執行的作業,例如回填索引、驗證不重複的索引限制,或驗證外鍵參照限制。

您可以查詢 INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS.SPANNER_STATE,瞭解外鍵建立狀態。

後續步驟