במסמך הזה מתוארות שיטות מומלצות להפעלת אלגוריתמים ב-Spanner Graph. הנושאים במאמר:
- שיטות מומלצות לסכימת גרף לאלגוריתמים
- טיפול בפלט של האלגוריתם
- הגדרת
machine_categoryלעומסי עבודה גדולים - הפחתת מגבלות הקיבולת האזוריות באמצעות
fallback_compute_region - שימוש חוזר במחשוב לאיטרציה מהירה
- הבחנה בין סוגי רכיבים בפלט
שיטות מומלצות לעבודה עם סכימות של גרפים באלגוריתמים
אם אתם משתמשים בתוויות ומאפיינים מותאמים אישית ב-Spanner Graph, מומלץ תמיד לחשוף מפתחות של רכיבים כמאפיינים. כך תוכלו לגשת למאפייני המפתח האלה בסעיף RETURN של שאילתת האלגוריתם, ולהשתמש בהם כדי לזהות את רכיב התרשים שהאלגוריתם יוצר בשבילו פלט.
טיפול בפלט של האלגוריתם
בקטע הזה מפורטות המלצות לגבי הנתונים שצריך להחזיר מהפלט של האלגוריתם, ואיפה לשמור את התוצאות שהוחזרו.
מה להחזיר
כשהחתימה של פלט האלגוריתם מכילה רכיבי תרשים, Spanner Graph מאפשר להחזיר כל מאפיין של הרכיבים האלה. כדי להקטין את עלות העיבוד, מומלץ לצמצם את רשימת הנכסים שיוחזרו. לדוגמה, אפשר להחזיר רק מאפיינים שהם מפתחות של אלמנט, כי המפתחות נחוצים לזיהוי האלמנט.
איפה לשמור את הנתונים
Spanner Graph תומך בשמירת תוצאת שאילתת אלגוריתם ב-Cloud Storage או בחזרה לאותו מופע של Spanner Graph שבו התחלתם את השאילתה.
שמירת הנתונים בחזרה ב-Spanner מאפשרת לכל הפעולות ב-Spanner לגשת לתוצאות של האלגוריתם באופן מקורי. לדוגמה, אפשר להריץ את WeaklyConnectedComponents, ולהחזיר את cluster_id לתרשים.
לאחר מכן, מריצים את PageRank עבור תרשים קלט עם cluster_id ספציפי.
תכונות של Spanner כמו סנכרון שינויים בזרמי נתונים מעבירות את הפלט של האלגוריתם החדש למערכות במורד הזרם. אם רוצים להשתמש בתוצאות של אלגוריתם ב-Spanner, מומלץ לשמור אותן ב-Spanner.
למרות ש-Spanner Graph משתמש בדרכים יעילות לאסוף את פלט האלגוריתם באצווה ולשמור אותו ב-Spanner, כל פעולות הכתיבה חייבות לעבור דרך אותו עותק מוביל. אם כבר יש לכם עומסי עבודה קריטיים שתופסים את הקיבולת של המנהל, כדאי להריץ את האלגוריתמים לסירוגין כדי שלא יתחרו עם עומסי העבודה הקריטיים.
אם אתם לא מתכננים להשתמש בפלט של האלגוריתם ב-Spanner, או אם אתם רוצים להעריך את הפלט של האלגוריתם לפני שאתם מטמיעים אותו במקור הנתונים הראשי, כדאי לשקול לשמור את הנתונים ב-Cloud Storage. פורמטים נתמכים של קבצים
שיקולים בבניית מודל נתונים להרחבת הגרף
בקטע הזה נדון בכמה שיקולים של בניית מודלים של נתונים כששומרים פלט של אלגוריתם ב-Spanner.
מאפיינים לעומת קצוות
האלגוריתמים יכולים להפיק מגוון תובנות, כולל:
- מדדים ברמת הצומת (לדוגמה, ציון מרכזיות). אפשר לשמור אותן כמאפיינים חדשים בצומת.
- תובנות לגבי זוגות (לדוגמה, דמיון בין שני צמתים). אפשר לשמור אותם כקשתות חדשות בין שני הצמתים, עם ערך הפלט כמאפיין של הקשת.
- אלגוריתמים לזיהוי קהילות מזהים קהילות לוגיות בתרשים ויכולים להקצות קהילה אחת או יותר לצומת נתון. אפשר ליצור מודל של חברות בקהילה כמאפיין חדש בצומת, על ידי תיוג של כל צומת חבר במזהה של הקהילה שהוקצתה לו. אפשר גם ליצור מודל של חברות בקהילה בתור תת-תרשימים חדשים, ולאחסן את הקהילות הלוגיות בתור סוג חדש של צמתים בתרשים עם קצוות שמחברים אותם לצמתים של החברים. אם אתם רוצים לדעת לאיזו קהילה צומת שייך כשאתם ניגשים אליו, יכול להיות שהמאפיין Community יספיק. תרשים משנה של קהילה יכול להתאים יותר כשרוצים לנווט לפי קהילה (לדוגמה, למצוא צמתים באותה קהילה כמו צומת התחלה). בהתאם לאופן שבו אתם מתכננים להשתמש במידע מהקהילה, אתם יכולים לבחור באפשרות אחת או בשתי האפשרויות.
סכימה מוגדרת מראש לעומת סכימה גמישה
לפני ששומרים את הפלט של האלגוריתם ב-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 מתאימה. אם בתרשים הקלט יש יותר ממיליארד צמתים ויותר מ-10 מיליארד קצוות, מומלץ לבחור במפורש את 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;