本文將說明使用 SQL 檢視表建立圖表的優點。本文說明使用檢視表建立圖表的優點、需求條件和注意事項,協助您決定要使用資料表還是檢視表建立圖表。
如要瞭解如何從檢視表建立圖表,請參閱「從 SQL 檢視表建立屬性圖」。
使用檢視表而非資料表建立圖表的好處
SQL 檢視表是由 SQL 查詢定義的虛擬資料表。在 Spanner 中,每當執行參照檢視表的查詢時,系統就會執行定義檢視表的查詢。Spanner 檢視表並非 materialized view,因為這類檢視表不會將定義檢視表的查詢結果,儲存為資料儲存庫中的實際資料表。詳情請參閱「檢視表總覽」。您可以從 SQL 檢視表建立圖表元素,但無法建立查詢圖表的檢視表。
檢視表可做為資料表和圖形結構定義之間的抽象層,提供多項優點,而使用資料表建立圖形時,則無法享有這些優點。
資料列層級存取控管。使用定義者權限檢視畫面的安全權限,在資料列層級對圖表資料套用精細的存取控管。確保使用者只能查詢有權查看的節點和邊。
彈性的資料建模。建立圖表元素前,請先使用檢視表和查詢,塑造及轉換關聯資料。檢視表的查詢可讓您篩選資料列、合併資料欄、取消巢狀結構重複欄位 (例如
ARRAY),或使用遠端函式計算屬性。從無結構定義資料轉換為正規化資料。從無結構定義資料建立檢視表,明確定義節點和邊緣類型。這有助於正式建立資料中的關係。
使用檢視表建立圖表的需求條件
使用檢視畫面建立圖表元素時,必須遵守下列規定:
指定圖表元素時,請使用 KEY 子句
使用檢視表建立節點或邊緣元素時,必須明確定義可唯一識別圖表元素的資料欄。如要這麼做,請在節點或邊緣元素定義中使用 KEY 子句。如要瞭解如何在建立圖表元素時使用 KEY 子句,請參閱本文和「從 SQL 檢視表建立 Spanner Graph」中的程式碼範例。
確保節點和邊緣鍵不重複
屬性圖中的每個節點和邊緣都必須有專屬索引鍵。使用檢視表定義圖表元素時,您可以選擇如何驗證元素索引鍵的唯一性:
- 嚴格金鑰驗證 (預設):Spanner 會驗證檢視表是否遵循支援的查詢模式,確保金鑰不重複。
- 停用索引鍵驗證 (任何 SQL 查詢):如果設定
validate_element_key_uniqueness = false圖表選項,則可使用任何 SQL 查詢。在這種模式下,您必須確保元素索引鍵不重複。
嚴格金鑰驗證 (預設)
根據預設,Spanner 會驗證定義節點或邊緣資料表的檢視表是否符合下列其中一種模式,確保每個節點或邊緣都是不重複的:
您可以搭配使用其他 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));