本文說明在 Spanner Graph 執行演算法的最佳做法。涵蓋的主題如下:
- 演算法適用的圖形結構定義最佳做法
- 處理演算法輸出內容
- 為大型工作負載指定
machine_category - 使用
fallback_compute_region減輕區域容量限制 - 重複使用運算資源,加快疊代速度
- 在輸出內容中區分元素類型
演算法的圖表結構定義最佳做法
如果您在 Spanner Graph 中使用自訂標籤和屬性,建議一律將元素索引鍵公開為屬性。這樣一來,您就能在演算法查詢的 RETURN 子句中存取這些金鑰屬性,並使用這些屬性識別演算法產生輸出內容的圖表元素。
處理演算法輸出內容
本節提供建議,說明演算法輸出內容應傳回哪些項目,以及傳回的結果應儲存在何處。
需寄回的項目
如果演算法的輸出簽章包含圖表元素,Spanner Graph 可讓您傳回這些元素的任何屬性。為降低處理成本,建議您盡可能減少要傳回的屬性清單。舉例來說,只傳回屬於元素鍵的屬性,因為鍵是識別元素所必需。
儲存位置
Spanner Graph 支援將演算法查詢結果保存至 Cloud Storage,或保存回您啟動查詢的相同 Spanner Graph 執行個體。
將資料保存回 Spanner,即可讓所有 Spanner 作業原生存取演算法輸出內容。舉例來說,您可以執行 WeaklyConnectedComponents,然後將 cluster_id 持久儲存回圖表。隨後,針對具有特定 cluster_id 的輸入圖表執行 PageRank。
Spanner 的變更串流等功能會將新的演算法輸出內容傳播至下游系統。如要在 Spanner 中使用演算法輸出內容,建議您將內容保留在 Spanner 中。雖然 Spanner Graph 會以有效率的方式批次處理演算法輸出內容,並將其永久儲存至 Spanner,但所有寫入作業都必須透過同一個領導者副本進行。如果重要工作負載已佔用領導者容量,建議您錯開演算法執行時間,以免與重要工作負載競爭。
如果您不打算在 Spanner 中使用演算法輸出內容,或想先評估演算法輸出內容,再擷取至主要資料來源,請考慮將內容保留至 Cloud Storage。查看支援的檔案格式。
擴增圖表的資料建模注意事項
本節說明將演算法輸出內容保存至 Spanner 時,一些資料建模考量。
屬性與邊緣
演算法可產生多種洞察資料,包括:
- 節點層級指標 (例如中心性分數)。這些屬性可以保留為節點上的新屬性。
- 成對洞察 (例如兩個節點之間的相似度)。這些值可以保留為兩個節點之間的新邊緣,並以輸出值做為邊緣屬性。
- 社群偵測演算法會找出圖譜中的邏輯社群,並將一或多個社群指派給特定節點。您可以將社群成員資格建模為節點上的新屬性,方法是為每個成員節點標記其所屬社群的 ID。您也可以將社群成員資格模擬為新的子圖,並將邏輯社群儲存為圖中的新類型節點,並以邊緣連結至成員節點。如果您想在存取節點時瞭解節點所屬的社群,社群屬性可能就已足夠。如要依社群瀏覽 (例如尋找與起始節點位於相同社群的節點),社群子圖可能更合適。視您打算如何使用社群資訊而定,您可以選擇其中一種或兩種。
預先定義的結構定義與彈性結構定義
將演算法輸出內容保留至 Spanner 之前,請先透過下列任一方式,在結構定義中定義目的地資料欄或資料表:
- 如果演算法用途穩定且已知,您可以事先新增其他資料欄或資料表。
- 如果您正在疊代並嘗試以不同方式擷取洞察資料 (例如試用不同的演算法、參數、輸入子圖),您可能需要彈性的方式來保存及區分多項實驗的輸出內容,而不必為每次執行更新 Spanner 結構定義。在這種情況下,您可以考慮將演算法產生的新屬性和邊緣,儲存在一般子資料表中。
如要將演算法產生的新屬性和邊緣儲存在一般子資料表中,請按照下列步驟操作:
步驟 1:建立一般子資料表
-- Create `AccountAlgoProperty` as a child table of `Account`, to store all
-- properties produced by algorithms for `Account`.
-- `algo_run_id`: a unique ID for a given algorithm run.
-- `int_val`: column to store integer algorithm output.
-- `float_val`: column to store float algorithm output.
CREATE TABLE AccountAlgoProperty (
id INT64 NOT NULL,
algo_run_id STRING(200) NOT NULL,
int_val INT64,
float_val FLOAT64
) PRIMARY KEY(id, algo_run_id),
INTERLEAVE IN PARENT Account;
-- Create `AccountAlgoEdge` as a child table of `Account`, to store all
-- outgoing edges produced by algorithms for `Account`.
-- `algo_run_id`: a unique ID for a given algorithm run.
-- `to_id`: destination `Account` id.
-- `int_val`: column to store integer algorithm output.
-- `float_val`: column to store float algorithm output.
CREATE TABLE AccountAlgoEdge (
id INT64 NOT NULL,
algo_run_id STRING(200) NOT NULL,
to_id INT64 NOT NULL,
int_val INT64,
float_val FLOAT64,
CONSTRAINT FK_AccountId FOREIGN KEY (to_id) REFERENCES Account (id) NOT ENFORCED,
) PRIMARY KEY(id, algo_run_id, to_id),
INTERLEAVE IN PARENT Account;
步驟 2:將演算法產生的屬性和邊緣,以及產生這些屬性和邊緣的專屬 algo_run_id,儲存為子資料表資料列。
-- Store PageRank score as property in child table.
EXPORT DATA
OPTIONS (format = "CLOUD_SPANNER",
table = "AccountAlgoProperty",
write_mode = 'upsert_ignore_all' ) AS
GRAPH FinGraph
CALL PageRank(node_labels => ['Account'], edge_labels => ['Transfers'])
RETURN node.id, "page_rank_123" AS algo_run_id, score As float_val;
-- Store ShortestPath output as edge in child table.
EXPORT DATA
OPTIONS (format = "CLOUD_SPANNER",
table = "AccountAlgoEdge",
write_mode = 'upsert_ignore_all' ) AS
GRAPH FinGraph
CALL ShortestPath(
source_nodes => ARRAY {
MATCH (n:Account {id: 7})
RETURN n
},
target_nodes => ARRAY {
MATCH (n:Account {id: 16})
RETURN n
}
) YIELD source_node, target_node, path, cost
RETURN source_node.id AS id, "shortest_path_456" AS algo_run_id,
target_node.id AS to_id, PATH_LENGTH(path) AS int_val, cost AS float_val;
步驟 3:使用 GRAPH_TABLE 存取演算法輸出內容
SELECT acct.id, prop.float_val AS page_rank_score
FROM GRAPH_TABLE(
FinGraph
MATCH (n:Account)
RETURN n.id
) acct JOIN AccountAlgoProperty prop ON acct.id = prop.id
AND prop.algo_run_id = 'page_rank_123';
SELECT acct.id, edge.to_id, edge.int_val AS path_len, edge.float_val AS cost
FROM GRAPH_TABLE(
FinGraph
MATCH (n:Account)
RETURN n.id
) acct JOIN AccountAlgoEdge edge ON acct.id = edge.id
AND edge.algo_run_id = 'shortest_path_456';
步驟 4:(選用) 建立以演算法產生的屬性和邊緣擴增的邏輯圖表,方便存取演算法輸出內容。
-- Create a view that aggregates non-null algorithm properties per node into
-- name-value pairs in JSON.
CREATE OR REPLACE VIEW AccountWithAlgoProperties SQL SECURITY INVOKER AS
SELECT
n.id, ANY_VALUE(n.create_time) AS create_time,
ANY_VALUE(n.is_blocked) AS is_blocked, ANY_VALUE(n.nick_name) AS nick_name,
JSON_OBJECT(
IF(COUNT(c.algo_run_id) = 0, [], ARRAY_AGG(c.algo_run_id)),
IF(COUNT(c.algo_run_id) = 0, [], ARRAY_AGG(
COALESCE(
IF (c.int_val IS NULL, NULL, TO_JSON(c.int_val)),
IF (c.float_val IS NULL, NULL, TO_JSON(c.float_val))
)))) AS algo_props
FROM Account AS n LEFT JOIN AccountAlgoProperty AS c ON n.id = c.id
GROUP BY n.id;
-- Create FinGraphAugmented with algorithm generated properties and edges.
CREATE OR REPLACE PROPERTY GRAPH FinGraphAugmented
NODE TABLES (
AccountWithAlgoProperties AS Account
KEY(id)
LABEL Account PROPERTIES(
create_time,
id,
is_blocked,
nick_name,
algo_props),
Person
)
EDGE TABLES (
PersonOwnAccount
SOURCE KEY (id) REFERENCES Person (id)
DESTINATION KEY (account_id) REFERENCES Account (id)
LABEL Owns,
AccountTransferAccount
SOURCE KEY (id) REFERENCES Account (id)
DESTINATION KEY (to_id) REFERENCES Account (id)
LABEL Transfers,
AccountAlgoEdge
SOURCE KEY (id) REFERENCES Account (id)
DESTINATION KEY (to_id) REFERENCES Account (id)
);
然後,您可以在圖形查詢中直接存取演算法屬性,並瀏覽演算法產生的邊緣:
-- Retrieve PageRank score property in graph query.
GRAPH FinGraphAugmented
MATCH (a:Account)
RETURN a.id, a.algo_props.page_rank_123 AS page_rank
ORDER BY page_rank DESC
LIMIT 5;
-- Navigate through ShortestPath edge in graph query.
GRAPH FinGraphAugmented
MATCH (s:Account {id: 7})-[e:AccountAlgoEdge {algo_run_id : 'shortest_path_456'}]->(d:Account)
RETURN s.id AS src, d.id AS dst, e.int_val AS path_len, e.float_val AS cost
針對大型工作負載指定 machine_category
對於大多數工作負載,default machine_category 是合適的選擇。如果輸入圖形有超過 10 億個節點和超過 100 億條邊緣,建議您明確選擇 large 做為 machine_category。
使用 fallback_compute_region 減輕區域容量限制
如果 Spanner 執行個體的主區域暫時遇到運算資源限制,請在與執行個體主區域相同的管轄區內,指定fallback_compute_region。這樣一來,如果主區域沒有可用運算資源,Spanner Graph 就會自動改為在備用區域佈建運算資源。
重複使用運算資源,快速疊代
如果您要對小型資料集使用不同演算法或輸入參數進行實驗,以便快速疊代,建議使用 max_idle_time。較大的 max_idle_time 可讓 Spanner Graph 重複使用已佈建的運算資源,處理更多演算法工作負載。這可減少冷啟動隨選運算資源的負擔,並降低因暫時缺乏容量而無法佈建運算資源的風險。請注意,演算法運算在閒置時會計費。
區分輸出內容中的元素類型
如果演算法輸出內容包含多個元素類型,您可能需要在輸出內容中加入 ELEMENT_DEFINITION_NAME,以便區分這些類型。例如:
EXPORT DATA OPTIONS (
uri = "gs://bucket-name/page_rank.csv",
format = "csv",
overwrite = TRUE) AS
GRAPH FinGraph
CALL PageRank()
YIELD node, score
RETURN ELEMENT_DEFINITION_NAME(node) AS node_type, node.id, score;