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

請參閱本文,瞭解使用 SQL 檢視區塊建立圖表的優點。這份文件包含使用檢視畫面建立圖表的優點需求條件注意事項,可協助您決定要使用資料表或檢視畫面建立圖表。

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

使用檢視區塊建立圖表的好處 (而非資料表)

SQL 檢視表是由 SQL 查詢定義的虛擬資料表。在 Spanner 中,每次執行參照檢視區塊的查詢時,系統都會執行定義檢視區塊的查詢。Spanner 檢視區塊不是具體化檢視區塊,因為這類檢視區塊不會將定義檢視區塊的查詢結果儲存為資料儲存空間中的實際資料表。詳情請參閱「檢視畫面總覽」。您可以從 SQL 檢視區塊建立圖表元素,但無法建立查詢圖表的檢視區塊。

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

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

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

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

使用檢視區塊建立節點或邊緣元素時,您必須明確定義可專屬識別圖表元素的資料欄。如要執行這項操作,請在節點或邊緣元素定義中使用 KEY 子句。如要瞭解如何在建立圖形元素時使用 KEY 子句,請參閱本文和「從 SQL 檢視區塊建立 Spanner Graph」中的程式碼範例。

使用可確保節點和邊緣不重複的檢視畫面

定義節點或邊緣資料表的檢視區塊必須遵循下列其中一種模式,確保節點和邊緣是唯一的:

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

  • 模式 2:檢視畫面使用 GROUP BYSELECT DISTINCT 子句。

您可以搭配這些模式使用其他 SQL 運算子,例如 WHEREHAVINGORDER BYLIMITTABLESAMPLE。這些運算子會篩選或排序結果,但不會改變模式提供的基礎唯一性保證。

模式 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 BYSELECT DISTINCT 子句

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

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

  • SELECT DISTINCTKEY 子句資料欄必須與 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)
  );

使用檢視區塊的注意事項

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

屬性圖查詢效能

在執行資料轉換的檢視區塊上定義圖形元素時 (例如 GROUP BYUNNESTJOIN 運算),請仔細評估您用途的查詢效能。請注意,每當查詢執行元素模式比對時,Spanner 都會執行檢視區塊的查詢定義。

圖表結構定義最佳化

使用檢視畫面定義圖表元素時,部分圖表結構定義最佳化可能不如使用資料表定義圖表元素有效。

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

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

使用 GROUP BYDISTINCT 子句定義的檢視區塊

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

使用以檢視區塊為基礎的圖表修改資料

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

圖表錯誤處理,確保資料完整性

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

舉例來說,當您從無結構定義轉換為正式圖表時,請使用 CHECK 限制條件驗證基本資料表 (GraphNodeGraphEdge) 中的資料。下列程式碼會在 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));

後續步驟