從 SQL 檢視區塊建立的圖表總覽

本文將說明使用 SQL 檢視表建立圖表的優點。本文說明使用檢視表建立圖表的優點、需求條件和注意事項,協助您決定要使用資料表還是檢視表建立圖表。

如要瞭解如何從檢視表建立圖表,請參閱「從 SQL 檢視表建立屬性圖」。

使用檢視表而非資料表建立圖表的好處

SQL 檢視表是由 SQL 查詢定義的虛擬資料表。在 Spanner 中,每當執行參照檢視表的查詢時,系統就會執行定義檢視表的查詢。Spanner 檢視表並非 materialized view,因為這類檢視表不會將定義檢視表的查詢結果,儲存為資料儲存庫中的實際資料表。詳情請參閱「檢視表總覽」。您可以從 SQL 檢視表建立圖表元素,但無法建立查詢圖表的檢視表。

檢視表可做為資料表和圖形結構定義之間的抽象層,提供多項優點,而使用資料表建立圖形時,則無法享有這些優點。

使用檢視表建立圖表的需求條件

使用檢視畫面建立圖表元素時,必須遵守下列規定:

指定圖表元素時,請使用 KEY 子句

使用檢視表建立節點或邊緣元素時,必須明確定義可唯一識別圖表元素的資料欄。如要這麼做,請在節點或邊緣元素定義中使用 KEY 子句。如要瞭解如何在建立圖表元素時使用 KEY 子句,請參閱本文和「從 SQL 檢視表建立 Spanner Graph」中的程式碼範例。

確保節點和邊緣鍵不重複

屬性圖中的每個節點和邊緣都必須有專屬索引鍵。使用檢視表定義圖表元素時,您可以選擇如何驗證元素索引鍵的唯一性:

嚴格金鑰驗證 (預設)

根據預設,Spanner 會驗證定義節點或邊緣資料表的檢視表是否符合下列其中一種模式,確保每個節點或邊緣都是不重複的:

  • 模式 1:檢視表使用單一資料表的主鍵。

  • 模式 2:檢視表使用 GROUP BY 或 SELECT DISTINCT 子句。

您可以搭配使用其他 SQL 運算子,例如 WHERE、HAVING、ORDER BY、LIMIT 和 TABLESAMPLE。這些運算子會篩選或排序結果,但不會變更模式提供的基礎唯一性保證。

模式 1:使用單一資料表的主鍵

在這個模式中,檢視表會從單一資料表選取,且圖表定義中的 KEY 子句會與基礎資料表的主鍵資料欄相符。因此,檢視表產生的每個節點或邊緣資料列都是不重複的。

例如,下列指令會從 Account 資料表選取部分資料列。圖表 KEY(account_id) 與 Account 資料表的主鍵相符,可確保檢視表產生的每個資料列都不重複。

-- Table has PRIMARY KEY(account_id).
CREATE TABLE Account (
  account_id INT64 NOT NULL,
  customer_id INT64 NOT NULL,
  account_type STRING(MAX),
  balance INT64
) PRIMARY KEY(account_id);

-- Pattern 1: View uses the primary key from a single table.
CREATE VIEW SavingAccount
  SQL SECURITY INVOKER AS
    SELECT accnt.account_id, accnt.customer_id, accnt.balance
    FROM Account accnt
    WHERE accnt.account_type = 'saving';

CREATE PROPERTY GRAPH SavingAccountGraph
  NODE TABLES (
    -- The element KEY(account_id) matches the table's primary key.
    SavingAccount KEY(account_id)
  );

模式 2:使用 GROUP BY 或 SELECT DISTINCT 子句

在這個模式中,檢視表的查詢會使用 GROUP BY 或 SELECT DISTINCT 子句。KEY 子句中的資料欄必須與這些子句用來定義唯一性的資料欄相符:

  • GROUP BY:KEY 子句資料欄必須與 GROUP BY 子句中的所有資料欄相符。

  • SELECT DISTINCT:KEY 子句資料欄必須與 SELECT DISTINCT 清單中的資料欄相符。

GROUP BY 範例:

CREATE TABLE Customer (
  customer_id INT64,
  name STRING(MAX)
) PRIMARY KEY (customer_id);

CREATE TABLE SaleOrder (
  order_id INT64,
  customer_id INT64,
  amount INT64
) PRIMARY KEY (order_id);

CREATE VIEW CustomerOrder
  SQL SECURITY INVOKER AS
    SELECT
      s.order_id,
      ANY_VALUE(c.customer_id) AS customer_id,
      ANY_VALUE(c.name) AS customer_name
    FROM Customer c JOIN SaleOrder s ON c.customer_id = s.customer_id
    GROUP BY s.order_id;

CREATE PROPERTY GRAPH OrderGraph
  NODE TABLES (
    -- The KEY(order_id) matches the GROUP BY column in view definition.
    CustomerOrder KEY(order_id)
  );

SELECT DISTINCT 範例:

CREATE TABLE SaleOrder (
  order_id INT64,
  customer_id INT64,
  amount INT64
) PRIMARY KEY (order_id);

CREATE VIEW KeyCustomer SQL SECURITY INVOKER AS
  SELECT DISTINCT s.customer_id, s.amount
  FROM SaleOrder s
  WHERE s.amount > 1000;

CREATE PROPERTY GRAPH KeyCustomersGraph
  NODE TABLES (
    -- The KEY(customer_id, amount) matches the DISTINCT columns.
    KeyCustomer KEY(customer_id, amount)
  );

停用金鑰驗證 (任何 SQL 查詢)

如果檢視表使用的查詢不符合模式 1 或模式 2 (例如查詢彙整資料表時不含 GROUP BY 或 SELECT DISTINCT 子句),您可以設定圖表選項 validate_element_key_uniqueness = false,停用元素索引鍵驗證。

根據預設,validate_element_key_uniqueness 為 true。如果設為 false,Spanner 就不會在建立結構定義時,驗證檢視表的查詢定義。您可以在檢視表中使用任何 SQL 查詢,但必須確保 KEY 子句中指定的資料欄,包含每個節點或邊緣資料列的不重複值。

以下範例定義名為 CustomerOrderTrusted 的檢視表,在沒有 GROUP BY 子句的情況下彙整 Customer 和 SaleOrder 資料表。由於每筆銷售訂單都是不重複的,因此將 SaleOrder 與 Customer 彙整後,檢視結果中的 order_id 仍會保持不重複。不過,由於查詢使用 JOIN,且不遵循模式 1 或模式 2,Spanner 無法在語法上驗證唯一性。

只要在 OPTIONS 子句中指定 KEY(order_id) 並設定 validate_element_key_uniqueness = false,即可定義屬性圖,而不必修改檢視表查詢:

-- View uses a JOIN without GROUP BY or DISTINCT.
CREATE VIEW CustomerOrderTrusted
  SQL SECURITY INVOKER AS
    SELECT
      s.order_id,
      c.customer_id,
      c.name AS customer_name
    FROM Customer c JOIN SaleOrder s ON c.customer_id = s.customer_id;

-- Property graph disables element key uniqueness validation.
CREATE PROPERTY GRAPH OrderGraphTrusted
  NODE TABLES (
    CustomerOrderTrusted
      KEY(order_id)
      LABEL CustomerOrder PROPERTIES(
        order_id,
        customer_id,
        customer_name)
  ) OPTIONS (validate_element_key_uniqueness = false);

在檢視表使用遠端函式時啟用 volatile 資料欄

您可以在呼叫遠端函式 (LANGUAGE REMOTE) 的檢視表上定義屬性圖,方法是在 CREATE PROPERTY GRAPH 陳述式的 OPTIONS 子句中設定 allow_view_with_volatile_column = true。

根據預設,Spanner 不允許您在具有不穩定資料欄 (allow_view_with_volatile_column = false) 的檢視表上定義屬性圖。如果檢視表資料欄的運算式呼叫不穩定函式,則該資料欄為不穩定。如果函式的傳回值即使在單一陳述式執行期間,使用相同引數也會變更,則該函式為不穩定,例如遠端函式 (NOT DETERMINISTIC)。檢視表定義主體中的任何不穩定性 (例如 JOIN 條件或 WHERE 子句),也會導致檢視表中的所有投影資料欄不穩定。如需程式碼範例,請參閱「使用遠端函式計算屬性」。

使用檢視表的注意事項

使用檢視區塊定義圖表元素時,下列做法有助於設計及實作有效的圖表:

屬性圖查詢效能

在執行資料轉換 (例如 GROUP BY、UNNEST 或 JOIN 作業) 的檢視表上定義圖表元素時,請仔細評估用途的查詢效能。請注意,每當查詢執行元素模式比對時,Spanner 都會執行檢視表的查詢定義。

圖表結構定義最佳化

使用檢視表定義圖表元素時,某些圖表結構定義最佳化的效果,可能不如使用資料表定義圖表元素。

投影單一資料表主鍵的檢視表

如果檢視表是單一基礎資料表的投影,則對該基礎資料表進行的任何最佳化,仍會對圖表查詢有效。舉例來說,對基礎資料表套用下列技術,可為這些檢視表上定義的圖表元素提供類似的效能優勢:

使用 GROUP BY 或 DISTINCT 子句定義的檢視表

執行匯總 (例如 GROUP BY、SELECT DISTINCT) 或其他複雜轉換的檢視表,會失去與基礎資料表結構的直接關係。因此,對基礎資料表進行結構定義最佳化,可能無法為在檢視表上執行的圖表查詢提供相同的效能優勢。如果檢視表執行複雜的匯總作業,請仔細評估用途的查詢效能。

使用檢視表圖表修改資料

檢視表並非具體化,也就是說,檢視表不會將定義檢視表的查詢結果儲存為資料儲存庫中的資料表,而且是唯讀的。因此,如要插入、更新或捨棄透過檢視表建立的圖表中的節點或邊緣,請修改用於建立檢視表的資料表中的資料。

圖表錯誤處理,強制執行資料完整性

使用檢視表定義圖表元素時,請對基礎資料表強制執行資料完整性 (例如強制執行資料類型)。否則,基礎資料表中的資料可能無效,導致在執行階段查詢以檢視表為基礎的圖表時失敗。

舉例來說,當您從無結構定義轉換為正式圖表時,請使用 CHECK 限制來驗證基礎資料表 (GraphNode 和 GraphEdge) 中的資料。下列程式碼會在 JSON 屬性中套用這些限制,確保來源資料完整性,並防止執行階段查詢錯誤。

-- Enforce that the 'name' property exists for nodes with the 'person' label.
ALTER TABLE GraphNode
ADD CONSTRAINT NameMustExistForPersonConstraint
CHECK (IF(label = 'person', properties.name IS NOT NULL, TRUE));

-- Enforce that the 'name' property is a string for nodes with the 'person' label.
ALTER TABLE GraphNode
ADD CONSTRAINT PersonNameMustBeStringTypeConstraint
CHECK (IF(label = 'person', JSON_TYPE(properties.name) = 'string', TRUE));

後續步驟