このドキュメントでは、Spanner Graph でアルゴリズムを実行するためのベスト プラクティスについて説明します。ここでは次のトピックを扱います。
- アルゴリズムのグラフ スキーマのベスト プラクティス
- アルゴリズムの出力を処理する
- 大規模なワークロードに
machine_categoryを指定する - 高速イテレーションのためのコンピューティングの再利用
- 出力での要素タイプの区別
アルゴリズムのグラフ スキーマのベスト プラクティス
Spanner Graph でカスタマイズされたラベルとプロパティを使用する場合は、常に要素キーをプロパティとして公開することをおすすめします。これにより、アルゴリズム クエリの RETURN 句でこれらのキー プロパティにアクセスし、アルゴリズムが出力を生成するグラフ要素の識別に使用できます。
アルゴリズムの出力を処理する
このセクションでは、アルゴリズムの出力から何を返すか、返された結果をどこに保持するかについての推奨事項を紹介します。
返品するもの
アルゴリズムの出力シグネチャにグラフ要素が含まれている場合、Spanner Graph では、これらの要素の任意のプロパティを返すことができます。処理費用を削減するため、返すプロパティのリストを最小限にすることをおすすめします。たとえば、要素を識別するためにキーが必要なため、要素のキーであるプロパティのみを返します。
永続化する場所
Spanner Graph は、アルゴリズム クエリの結果を Cloud Storage に永続化するか、クエリを開始した同じ Spanner Graph インスタンスに永続化することをサポートしています。
Spanner に永続化すると、アルゴリズムの出力にすべての Spanner オペレーションからネイティブにアクセスできるようになります。たとえば、WeaklyConnectedComponent を実行し、cluster_id をグラフに保持できます。次に、特定の cluster_id を含む入力グラフに対して PageRank を実行します。変更ストリームなどの Spanner の機能は、新しいアルゴリズムの出力をダウンストリーム システムに伝播します。Spanner でアルゴリズムの出力を使用する場合は、Spanner に永続化することをおすすめします。Spanner Graph は、アルゴリズムの出力を Spanner にバッチ処理して永続化する効率的な方法を使用しますが、すべての書き込みは同じリーダー レプリカを通過する必要があります。リーダー容量を占有する重要なワークロードがすでに存在する場合は、重要なワークロードとの競合を避けるために、アルゴリズムの実行をずらすことを検討してください。
Spanner でアルゴリズムの出力を使用する予定がない場合や、プライマリ データソースに取り込む前にアルゴリズムの出力を評価する場合は、Cloud Storage に永続化することを検討してください。サポートされているファイル形式をご覧ください。
グラフを拡張するためのデータ モデリングの考慮事項
このセクションでは、アルゴリズムの出力を Spanner に永続化する際のデータ モデリングの考慮事項について説明します。
プロパティとエッジ
アルゴリズムは、次のようなさまざまな分析情報を生成できます。
- ノードレベルの指標(中心性スコアなど)。これらはノードの新しいプロパティとして保持できます。
- ペア単位の分析情報(2 つのノード間の類似度など)。これらは、出力値をエッジ プロパティとして持つ 2 つのノード間の新しいエッジとして永続化できます。
- コミュニティ検出アルゴリズムは、グラフ内の論理コミュニティを特定し、特定のノードに 1 つ以上のコミュニティを割り当てることができます。各メンバーノードに割り当てられたコミュニティの 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 億を超えるエッジがある場合は、machine_category に large を明示的に選択することをおすすめします。
高速イテレーションのためにコンピューティングを再利用する
高速なイテレーションのために、小規模なデータセットでさまざまなアルゴリズムや入力パラメータをテストする場合は、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;