סקירה כללית של תרשימים שנוצרו מתצוגות SQL

במאמר הזה מוסבר למה כדאי להשתמש בתצוגות SQL כדי ליצור תרשים. במאמר הזה נסביר על היתרונות של יצירת תרשימים באמצעות תצוגות, הדרישות והשיקולים שיעזרו לכם להחליט אם להשתמש בטבלאות או בתצוגות כדי ליצור תרשים.

במאמר יצירת תרשים מאפיינים מתצוגות SQL מוסבר איך יוצרים תרשים מתצוגות.

היתרונות של יצירת תרשימים באמצעות תצוגות במקום טבלאות

תצוגת SQL היא טבלה וירטואלית שמוגדרת על ידי שאילתת SQL. ב-Spanner, השאילתה שמגדירה תצוגה מופעלת בכל פעם שמופעלת שאילתה שמתייחסת לתצוגה. תצוגות ב-Spanner הן לא תצוגות מהותיות, כי הן לא שומרות את תוצאות השאילתה שמגדירה את התצוגה כטבלה בפועל במאגר הנתונים. מידע נוסף זמין במאמר סקירה כללית על תצוגות. אפשר ליצור רכיבי תרשים מתצוגות SQL, אבל אי אפשר ליצור תצוגה ששולחת שאילתה לתרשים.

לתצוגות יש כמה יתרונות כשכבת הפשטה בין טבלאות לבין סכימת גרף, שלא זמינים כשמשתמשים בטבלאות כדי ליצור גרף.

הדרישות לשימוש בתצוגות ליצירת תרשימים

כשמשתמשים בתצוגות כדי ליצור רכיבי תרשים, צריך לפעול לפי הדרישות הבאות:

משתמשים בסעיף KEY כשמציינים רכיב בתרשים

כשמשתמשים בתצוגות כדי ליצור רכיב צומת או קשת, צריך להגדיר במפורש את העמודות שמזהות באופן ייחודי את רכיב התרשים. כדי לעשות את זה, משתמשים בסעיף KEY בהגדרה של רכיב הצומת או הקשת. כדי ללמוד איך להשתמש בסעיף KEY כשיוצרים רכיב Spanner Graph, עיינו בדוגמאות הקוד במסמך הזה ובמאמר יצירת Spanner Graph מתצוגת SQL.

מוודאים שהמפתחות של הצמתים והקצוות ייחודיים

לכל צומת וקשת בתרשים מאפיינים צריך להיות מפתח ייחודי. כשמגדירים רכיבי תרשים באמצעות תצוגות, אפשר לבחור איך לאמת את הייחודיות של מפתח הרכיב:

אימות מפתחות מחמיר (ברירת מחדל)

כברירת מחדל, Spanner מוודא שהתצוגות שמגדירות טבלאות של צמתים או קצוות פועלות לפי אחת מהתבניות הבאות, כדי להבטיח שכל צומת או קצה יהיו ייחודיים:

  • תבנית 1: התצוגה משתמשת במפתח ראשי של טבלה אחת.

  • דפוס 2: התצוגה משתמשת בסעיף GROUP BY או SELECT DISTINCT.

אפשר להשתמש באופרטורים אחרים של 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 שמחברת בין הטבלאות Customer ו-SaleOrder בלי משפט GROUP BY. מכיוון שכל הזמנת מכירה היא ייחודית, צירוף של SaleOrder עם Customer שומר על הייחודיות של order_id בתוצאות התצוגה. עם זאת, מכיוון שהשאילתה משתמשת ב-JOIN ולא פועלת לפי דפוס 1 או דפוס 2, Spanner לא יכול לאמת את הייחודיות מבחינה תחבירית.

אם מציינים את KEY(order_id) ומגדירים את validate_element_key_uniqueness = false בסעיף OPTIONS, אפשר להגדיר את תרשים המאפיינים בלי לשנות את השאילתה של התצוגה:

-- 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);

הפעלת עמודות נדיפות כשתצוגות משתמשות בפונקציות מרוחקות

אפשר להגדיר תרשים מאפיינים בתצוגה שקוראת לפונקציה מרוחקת (LANGUAGE REMOTE) על ידי הגדרת allow_view_with_volatile_column = true בסעיף OPTIONS של ההצהרה CREATE PROPERTY GRAPH.

כברירת מחדל, 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));

המאמרים הבאים