תחילת העבודה עם Spanner ב-Ruby

מטרות

במדריך הזה נסביר איך לבצע את השלבים הבאים באמצעות ספריית הלקוח של Spanner ל-Ruby:

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

עלויות

במדריך הזה נעשה שימוש ב-Spanner, שהוא רכיב בתשלום שלGoogle Cloud. מידע על עלות השימוש ב-Spanner מופיע בקטע תמחור.

לפני שמתחילים

צריך לבצע את השלבים שמפורטים במאמר הגדרה, שכוללים יצירה והגדרה של פרויקט ברירת מחדל Google Cloud , הפעלת החיוב, הפעלת Cloud Spanner API והגדרת OAuth 2.0 כדי לקבל אישורי אימות לשימוש ב-Cloud Spanner API.

בפרט, חשוב להריץ את הפקודה gcloud auth application-default login כדי להגדיר את סביבת הפיתוח המקומית עם פרטי אימות.

הכנת סביבת Ruby מקומית

  1. אם הפריטים הבאים לא מותקנים במחשב הפיתוח, צריך להתקין אותם:

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

    git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples
    

    אפשרות נוספת היא להוריד את הדוגמה כקובץ ZIP ולחלץ אותה.

  3. עוברים לספרייה שמכילה את הקוד לדוגמה של Spanner:

    cd ruby-docs-samples/spanner/
    
  4. יחסי תלות של התקנות:

    bundle install
    
  5. מגדירים את משתנה הסביבה GOOGLE_CLOUD_PROJECT למזהה הפרויקט Google Cloud שלכם:

    export GOOGLE_CLOUD_PROJECT=[MY_PROJECT_ID]
    

יצירת מופע

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

במאמר יצירת מכונה מוסבר איך ליצור מכונת Spanner באמצעות אחת מהשיטות הבאות. אפשר לתת למופע שם test-instance כדי להשתמש בו עם נושאים אחרים במסמך הזה שמפנים למופע בשם test-instance.

  • ‫Google Cloud CLI
  • מסוף Google Cloud
  • ספריית לקוח (C++‎,‏ C#‎,‏ Go,‏ Java,‏ Node.js,‏ PHP,‏ Python או Ruby)

עיון בקבצים לדוגמה

מאגר הדוגמאות מכיל דוגמה שמראה איך להשתמש ב-Spanner עם Ruby.

מעיינים בקובץ spanner_samples.rb שבו מוסבר איך להשתמש ב-Spanner. בדוגמת הקוד מוצג איך ליצור מסד נתונים חדש ולהשתמש בו. הנתונים מבוססים על סכימת הדוגמה שמוצגת בדף סכימה ומודל נתונים.

יצירת מסד נתונים

GoogleSQL

bundle exec ruby spanner_samples.rb create_database test-instance example-db

PostgreSQL

bundle exec ruby spanner_postgresql_create_database.rb postgresql_create_database MY_PROJECT_ID test-instance example-db

הפרטים שמוצגים הם:

Created database example-db on instance test-instance
הקוד הבא יוצר מסד נתונים ושתי טבלאות במסד הנתונים.

GoogleSQL

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin

instance_path = database_admin_client.instance_path project: project_id, instance: instance_id

job = database_admin_client.create_database parent: instance_path,
                                            create_statement: "CREATE DATABASE `#{database_id}`",
                                            extra_statements: [
                                              "CREATE TABLE Singers (
      SingerId     INT64 NOT NULL,
      FirstName    STRING(1024),
      LastName     STRING(1024),
      SingerInfo   BYTES(MAX)
    ) PRIMARY KEY (SingerId)",

                                              "CREATE TABLE Albums (
      SingerId     INT64 NOT NULL,
      AlbumId      INT64 NOT NULL,
      AlbumTitle   STRING(MAX)
    ) PRIMARY KEY (SingerId, AlbumId),
    INTERLEAVE IN PARENT Singers ON DELETE CASCADE"
                                            ]

puts "Waiting for create database operation to complete"

job.wait_until_done!

puts "Created database #{database_id} on instance #{instance_id}"

PostgreSQL

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

def postgresql_create_database project_id:, instance_id:, database_id:
  # project_id  = "Your Google Cloud project ID"
  # instance_id = "Your Spanner instance ID"
  # database_id = "Your Spanner database ID"

  database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin project: project_id

  instance_path = database_admin_client.instance_path project: project_id, instance: instance_id

  job = database_admin_client.create_database parent: instance_path,
                                              create_statement: "CREATE DATABASE \"#{database_id}\"",
                                              database_dialect: :POSTGRESQL

  puts "Waiting for create database operation to complete"

  job.wait_until_done!

  puts "Created database #{database_id} on instance #{instance_id}"
end

השלב הבא הוא כתיבת נתונים למסד הנתונים.

יצירת לקוח מסד נתונים

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

# Imports the Google Cloud client library
require "google/cloud/spanner"

# Your Google Cloud Platform project ID
project_id = "YOUR_PROJECT_ID"

# Instantiates a client
spanner = Google::Cloud::Spanner.new project: project_id

# Your Cloud Spanner instance ID
instance_id = "my-instance"

# Your Cloud Spanner database ID
database_id = "my-database"

# Gets a reference to a Cloud Spanner instance database
database_client = spanner.client instance_id, database_id

# Execute a simple SQL statement
results = database_client.execute_query "SELECT 1"
results.rows.each do |row|
  puts row
end

מידע נוסף זמין במאמר בנושא Client.

כתיבת נתונים באמצעות DML

אפשר להוסיף נתונים באמצעות שפת טיפול בנתונים (DML) בעסקת קריאה-כתיבה.

משתמשים ב-execute_update() method כדי להריץ פקודת DML.

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id
row_count = 0

client.transaction do |transaction|
  row_count = transaction.execute_update(
    "INSERT INTO Singers (SingerId, FirstName, LastName) VALUES
     (12, 'Melissa', 'Garcia'),
     (13, 'Russell', 'Morales'),
     (14, 'Jacqueline', 'Long'),
     (15, 'Dylan', 'Shaw'),
     (16, 'Billie', 'Eillish'),
     (17, 'Judy', 'Garland'),
     (18, 'Taylor', 'Swift'),
     (19, 'Miley', 'Cyrus'),
     (20, 'Michael', 'Jackson'),
     (21, 'Ariana', 'Grande'),
     (22, 'Elvis', 'Presley'),
     (23, 'Kanye', 'West'),
     (24, 'Lady', 'Gaga'),
     (25, 'Nick', 'Jonas')"
  )
end

puts "#{row_count} records inserted."

מריצים את הדוגמה באמצעות הארגומנט write_using_dml.

bundle exec ruby spanner_samples.rb write_using_dml test-instance example-db

הפרטים שמוצגים הם:

 4 records inserted.

כתיבת נתונים באמצעות מוטציות

אפשר גם להוסיף נתונים באמצעות מוטציות.

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

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

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

client.commit do |c|
  c.insert "Singers", [
    { SingerId: 1, FirstName: "Marc",     LastName: "Richards" },
    { SingerId: 2, FirstName: "Catalina", LastName: "Smith"    },
    { SingerId: 3, FirstName: "Alice",    LastName: "Trentor"  },
    { SingerId: 4, FirstName: "Lea",      LastName: "Martin"   },
    { SingerId: 5, FirstName: "David",    LastName: "Lomond"   }
  ]
  c.insert "Albums", [
    { SingerId: 1, AlbumId: 1, AlbumTitle: "Total Junk" },
    { SingerId: 1, AlbumId: 2, AlbumTitle: "Go, Go, Go" },
    { SingerId: 2, AlbumId: 1, AlbumTitle: "Green" },
    { SingerId: 2, AlbumId: 2, AlbumTitle: "Forever Hold Your Peace" },
    { SingerId: 2, AlbumId: 3, AlbumTitle: "Terrified" }
  ]
end

puts "Inserted data"

מריצים את הדוגמה באמצעות הארגומנט insert_data.

bundle exec ruby spanner_samples.rb insert_data test-instance example-db

הפרטים שמוצגים הם:

Inserted data

הרצת שאילתות על נתונים באמצעות SQL

‫Spanner תומך בממשק SQL לקריאת נתונים, שאפשר לגשת אליו בשורת הפקודה באמצעות Google Cloud CLI או באופן פרוגרמטי באמצעות ספריית הלקוח של Spanner ל-Ruby.

בשורת הפקודה

מריצים את הצהרת ה-SQL הבאה כדי לקרוא את הערכים של כל העמודות מהטבלה Albums:

gcloud spanner databases execute-sql example-db --instance=test-instance \
    --sql='SELECT SingerId, AlbumId, AlbumTitle FROM Albums'

התוצאה:

SingerId AlbumId AlbumTitle
1        1       Total Junk
1        2       Go, Go, Go
2        1       Green
2        2       Forever Hold Your Peace
2        3       Terrified

שימוש בספריית הלקוח של Spanner ל-Ruby

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

משתמשים ב-method‏ Client#execute כדי להריץ את שאילתת ה-SQL. כדי לגשת לנתונים של עמודה ספציפית משורה, משתמשים בסמל Ruby‏ :ColumnName.

כך מריצים את השאילתה וניגשים לנתונים:

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

client.execute("SELECT SingerId, AlbumId, AlbumTitle FROM Albums").rows.each do |row|
  puts "#{row[:SingerId]} #{row[:AlbumId]} #{row[:AlbumTitle]}"
end

מריצים את הדוגמה באמצעות הארגומנט query_data.

bundle exec ruby spanner_samples.rb query_data test-instance example-db

אמורה להתקבל התוצאה הבאה:

1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified

שאילתה באמצעות פרמטר SQL

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

הנה דוגמה לשימוש בפרמטר בקטע WHERE כדי לשלוח שאילתה לגבי רשומות שמכילות ערך ספציפי של LastName.

GoogleSQL

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

sql_query = "SELECT SingerId, FirstName, LastName
             FROM Singers
             WHERE LastName = @lastName"

params      = { lastName: "Garcia" }
param_types = { lastName: :STRING }

client.execute(sql_query, params: params, types: param_types).rows.each do |row|
  puts "#{row[:SingerId]} #{row[:FirstName]} #{row[:LastName]}"
end

PostgreSQL

def spanner_postgresql_query_parameter project_id:, instance_id:, database_id:
  # project_id  = "Your Google Cloud project ID"
  # instance_id = "Your Spanner instance ID"
  # database_id = "Your Spanner database ID"

  require "google/cloud/spanner"

  spanner = Google::Cloud::Spanner.new project: project_id
  client  = spanner.client instance_id, database_id

  sql_query = "SELECT SingerId, FirstName, LastName FROM Singers WHERE FirstName LIKE $1"
  params = { p1: "A%" }

  results = client.execute sql_query, params: params

  results.rows.each do |row|
    puts "SingerId: #{row[:singerid]}"
    puts "FirstName: #{row[:firstname]}"
    puts "LastName: #{row[:lastname]}"
  end
end

מריצים את הדוגמה באמצעות הארגומנט query_with_parameter.

bundle exec ruby spanner_samples.rb query_with_parameter test-instance example-db

אמורה להתקבל התוצאה הבאה:

12 Melissa Garcia

קריאת נתונים באמצעות read API

בנוסף לממשק ה-SQL של Spanner, ‏ Spanner תומך גם בממשק קריאה.

משתמשים בשיטה Client#read של המחלקה Client כדי לקרוא שורות ממסד הנתונים.

כך קוראים את הנתונים:

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

client.read("Albums", [:SingerId, :AlbumId, :AlbumTitle]).rows.each do |row|
  puts "#{row[:SingerId]} #{row[:AlbumId]} #{row[:AlbumTitle]}"
end

מריצים את הדוגמה באמצעות הארגומנט read_data.

bundle exec ruby spanner_samples.rb read_data test-instance example-db

הפלט אמור להיראות כך:

1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified

עדכון הסכימה של מסד הנתונים

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

הוספת עמודה

אפשר להוסיף עמוד בשורת הפקודה באמצעות Google Cloud CLI או באופן פרוגרמטי באמצעות ספריית הלקוח של Spanner ל-Ruby.

בשורת הפקודה

כדי להוסיף את העמודה החדשה לטבלה, משתמשים בפקודה ALTER TABLE הבאה:

GoogleSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget INT64'

PostgreSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT'

הפרטים שמוצגים הם:

Schema updating...done.

שימוש בספריית הלקוח של Spanner ל-Ruby

כדי לשנות את הסכימה, משתמשים בשיטה Database#update של המחלקה Database:

GoogleSQL

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin

db_path = database_admin_client.database_path project: project_id,
                                              instance: instance_id,
                                              database: database_id

job = database_admin_client.update_database_ddl database: db_path,
                                                statements: [
                                                  "ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"
                                                ]

puts "Waiting for database update to complete"

job.wait_until_done!

puts "Added the MarketingBudget column"

PostgreSQL

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

def spanner_postgresql_add_column project_id:, instance_id:, database_id:
  # project_id  = "Your Google Cloud project ID"
  # instance_id = "Your Spanner instance ID"
  # database_id = "Your Spanner database ID"

  db_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin project: project_id

  db_path = db_admin_client.database_path project: project_id,
                                          instance: instance_id,
                                          database: database_id

  add_column_query = "ALTER TABLE Singers ADD COLUMN Age INTEGER"

  job = db_admin_client.update_database_ddl database: db_path,
                                            statements: [add_column_query]

  job.wait_until_done!

  if job.error?
    puts "Error while adding column. Code: #{job.error.code}. Message: #{job.error.message}"
    raise GRPC::BadStatus.new(job.error.code, job.error.message)
  end

  puts "Added Age column to Singers table in datbase #{database_id}"
end

מריצים את הדוגמה באמצעות הארגומנט add_column.

bundle exec ruby spanner_samples.rb add_column test-instance example-db

הפרטים שמוצגים הם:

Added the MarketingBudget column

כתיבת נתונים בעמודה החדשה

הקוד הבא כותב נתונים בעמודה החדשה. היא מגדירה את MarketingBudget ל-100000 בשורה עם מפתח Albums(1, 1) ול-500000 בשורה עם מפתח Albums(2, 2).

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

client.commit do |c|
  c.update "Albums", [
    { SingerId: 1, AlbumId: 1, MarketingBudget: 100_000 },
    { SingerId: 2, AlbumId: 2, MarketingBudget: 500_000 }
  ]
end

puts "Updated data"

מריצים את הדוגמה באמצעות הארגומנט update_data.

bundle exec ruby spanner_samples.rb update_data test-instance example-db

הפרטים שמוצגים הם:

Updated data

אפשר גם להריץ שאילתת SQL או קריאת נתונים כדי לאחזר את הערכים שזה עתה כתבתם.

הנה הקוד להרצת השאילתה:

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

client.execute("SELECT SingerId, AlbumId, MarketingBudget FROM Albums").rows.each do |row|
  puts "#{row[:SingerId]} #{row[:AlbumId]} #{row[:MarketingBudget]}"
end

כדי להריץ את השאילתה הזו, מריצים את הדוגמה באמצעות הארגומנט query_data_with_new_column.

bundle exec ruby spanner_samples.rb query_data_with_new_column test-instance example-db

הפרטים שמוצגים הם:

1 1 100000
1 2
2 1
2 2 500000
2 3

עדכון נתונים

אפשר לעדכן נתונים באמצעות DML בעסקת קריאה-כתיבה.

משתמשים ב-execute_update() method כדי להריץ פקודת DML.

GoogleSQL

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner         = Google::Cloud::Spanner.new project: project_id
client          = spanner.client instance_id, database_id
transfer_amount = 200_000

client.transaction do |transaction|
  first_album = transaction.execute(
    "SELECT MarketingBudget from Albums
     WHERE SingerId = 1 and AlbumId = 1"
  ).rows.first
  second_album = transaction.execute(
    "SELECT MarketingBudget from Albums
    WHERE SingerId = 2 and AlbumId = 2"
  ).rows.first
  raise "The second album does not have enough funds to transfer" if second_album[:MarketingBudget] < transfer_amount

  new_first_album_budget  = first_album[:MarketingBudget] + transfer_amount
  new_second_album_budget = second_album[:MarketingBudget] - transfer_amount

  transaction.execute_update(
    "UPDATE Albums SET MarketingBudget = @albumBudget WHERE SingerId = 1 and AlbumId = 1",
    params: { albumBudget: new_first_album_budget }
  )
  transaction.execute_update(
    "UPDATE Albums SET MarketingBudget = @albumBudget WHERE SingerId = 2 and AlbumId = 2",
    params: { albumBudget: new_second_album_budget }
  )
end

puts "Transaction complete"

PostgreSQL

def spanner_postgresql_dml_getting_started_update project_id:, instance_id:, database_id:
  # project_id  = "Your Google Cloud project ID"
  # instance_id = "Your Spanner instance ID"
  # database_id = "Your Spanner database ID"

  require "google/cloud/spanner"

  spanner = Google::Cloud::Spanner.new project: project_id
  client = spanner.client instance_id, database_id

  client.transaction do |transaction|
    transaction.execute_update(
      "UPDATE Singers SET Rating = $1 WHERE SingerId = 1",
      params: { p1: BigDecimal(4) },
      types: { p1: :PG_NUMERIC }
    )
  end

  puts "Transaction complete"
end

מריצים את הדוגמה באמצעות הארגומנט write_with_transaction_using_dml.

bundle exec ruby spanner_samples.rb write_with_transaction_using_dml test-instance example-db

הפרטים שמוצגים הם:

Transaction complete

שימוש באינדקס משני

נניח שרוצים לאחזר את כל השורות של Albums שיש להן ערכים של AlbumTitle בטווח מסוים. אפשר לקרוא את כל הערכים מהעמודה AlbumTitle באמצעות הצהרת SQL או קריאת קובץ, ואז להשליך את השורות שלא עומדות בקריטריונים. אבל סריקה מלאה של הטבלה היא פעולה יקרה, במיוחד בטבלאות עם הרבה שורות. במקום זאת, אפשר להאיץ את אחזור השורות כשמחפשים לפי עמודות שאינן מפתח ראשי, על ידי יצירת אינדקס משני בטבלה.

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

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

הוספת אינדקס משני

אפשר להוסיף אינדקס בשורת הפקודה באמצעות ה-CLI של gcloud או באופן פרוגרמטי באמצעות ספריית הלקוח של Spanner ל-Ruby.

בשורת הפקודה

משתמשים בפקודה CREATE INDEX הבאה כדי להוסיף אינדקס למסד הנתונים:

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)'

הפרטים שמוצגים הם:

Schema updating...done.

שימוש בספריית הלקוח של Spanner ל-Ruby

משתמשים ב-method‏ Database#update של המחלקה Database כדי להוסיף אינדקס:

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin

db_path = database_admin_client.database_path project: project_id,
                                              instance: instance_id,
                                              database: database_id

job = database_admin_client.update_database_ddl database: db_path,
                                                statements: [
                                                  "CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"
                                                ]

puts "Waiting for database update to complete"

job.wait_until_done!

puts "Added the AlbumsByAlbumTitle index"

מריצים את הדוגמה באמצעות הארגומנט create_index.

bundle exec ruby spanner_samples.rb create_index test-instance example-db

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

Added the AlbumsByAlbumTitle index

קריאה באמצעות האינדקס

בשאילתות SQL, ‏ Spanner משתמש באופן אוטומטי באינדקס מתאים. בממשק הקריאה, צריך לציין את האינדקס בבקשה.

כדי להשתמש באינדקס בממשק הקריאה, צריך לספק פרמטר index לשיטה read של המחלקה Client.

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

result = client.read "Albums", [:AlbumId, :AlbumTitle],
                     index: "AlbumsByAlbumTitle"

result.rows.each do |row|
  puts "#{row[:AlbumId]} #{row[:AlbumTitle]}"
end

מריצים את הדוגמה באמצעות הארגומנט read_data_with_index.

bundle exec ruby spanner_samples.rb read_data_with_index test-instance example-db

הפרטים שמוצגים הם:

2 Forever Hold Your Peace
2 Go, Go, Go
1 Green
3 Terrified
1 Total Junk

הוספת אינדקס לקריאות של אינדקס בלבד

יכול להיות ששמתם לב שבדוגמה הקודמת של קריאה לא נכללת קריאה של העמודה MarketingBudget. הסיבה לכך היא שממשק הקריאה של Spanner לא תומך באפשרות של צירוף אינדקס לטבלת נתונים כדי לחפש ערכים שלא מאוחסנים באינדקס.

יוצרים הגדרה חלופית של AlbumsByAlbumTitle ששומרת עותק של MarketingBudget באינדקס.

בשורת הפקודה

GoogleSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)

PostgreSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) INCLUDE (MarketingBudget)

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

Schema updating...done.

שימוש בספריית הלקוח של Spanner ל-Ruby

משתמשים בשיטה Database#update של המחלקה Database כדי להוסיף אינדקס עם פסקה STORING:

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin

db_path = database_admin_client.database_path project: project_id,
                                              instance: instance_id,
                                              database: database_id

job = database_admin_client.update_database_ddl database: db_path,
                                                statements: [
                                                  "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)
   STORING (MarketingBudget)"
                                                ]

puts "Waiting for database update to complete"

job.wait_until_done!

puts "Added the AlbumsByAlbumTitle2 storing index"

מריצים את הדוגמה באמצעות הארגומנט create_storing_index.

bundle exec ruby spanner_samples.rb create_storing_index test-instance example-db

הפרטים שמוצגים הם:

Added the AlbumsByAlbumTitle2 index

עכשיו אפשר להריץ קריאה שמביאה את כל העמודות AlbumId, AlbumTitle ו-MarketingBudget מהאינדקס AlbumsByAlbumTitle2:

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

result = client.read "Albums", [:AlbumId, :AlbumTitle, :MarketingBudget],
                     index: "AlbumsByAlbumTitle2"

result.rows.each do |row|
  puts "#{row[:AlbumId]} #{row[:AlbumTitle]} #{row[:MarketingBudget]}"
end

מריצים את הדוגמה באמצעות הארגומנט read_data_with_storing_index.

bundle exec ruby spanner_samples.rb read_data_with_storing_index test-instance example-db

הפלט אמור להיראות כך:

2 Forever Hold Your Peace 300000
2 Go, Go, Go
1 Green
3 Terrified
1 Total Junk 300000

אחזור נתונים באמצעות טרנזקציות לקריאה בלבד

נניח שרוצים לבצע יותר מקריאה אחת באותה חותמת זמן. עסקאות לקריאה בלבד מתבססות על קידומת עקבית של היסטוריית אישור העסקאות, כך שהאפליקציה תמיד מקבלת נתונים עקביים. משתמשים באובייקט Snapshot כדי להריץ טרנזקציות לקריאה בלבד. משתמשים ב-method‏ snapshot של המחלקה Client כדי לקבל אובייקט Snapshot.

בדוגמה הבאה מוצג איך להריץ שאילתה ולבצע קריאה באותה טרנזקציה לקריאה בלבד:

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

client.snapshot do |snapshot|
  snapshot.execute("SELECT SingerId, AlbumId, AlbumTitle FROM Albums").rows.each do |row|
    puts "#{row[:AlbumId]} #{row[:AlbumTitle]} #{row[:SingerId]}"
  end

  # Even if changes occur in-between the reads, the transaction ensures that
  # both return the same data.
  snapshot.read("Albums", [:AlbumId, :AlbumTitle, :SingerId]).rows.each do |row|
    puts "#{row[:AlbumId]} #{row[:AlbumTitle]} #{row[:SingerId]}"
  end
end

מריצים את הדוגמה באמצעות הארגומנט read_only_transaction.

bundle exec ruby spanner_samples.rb read_only_transaction test-instance example-db

הפלט אמור להיראות כך:

2 Forever Hold Your Peace 2
2 Go, Go, Go 1
1 Green 2
3 Terrified 2
1 Total Junk 1
1 Total Junk 1
2 Go, Go, Go 1
1 Green 2
2 Forever Hold Your Peace 2
3 Terrified 2

הסרת המשאבים

כדי להימנע מחיובים נוספים בחשבון לחיוב ב-Cloud על המשאבים שבהם השתמשתם במדריך הזה, צריך להשליך את מסד הנתונים ולמחוק את המופע שיצרתם.

מחיקת מסד הנתונים

אם מוחקים מופע, כל מסדי הנתונים שבו נמחקים אוטומטית. בשלב הזה נסביר איך למחוק מסד נתונים בלי למחוק את המופע (עדיין תחויבו על המופע).

בשורת הפקודה

gcloud spanner databases delete example-db --instance=test-instance

שימוש במסוף Google Cloud

  1. נכנסים לדף Spanner Instances במסוף Google Cloud .

    כניסה לדף Instances

  2. לוחצים על המופע.

  3. לוחצים על מסד הנתונים שרוצים למחוק.

  4. בדף פרטי מסד הנתונים, לוחצים על מחיקה.

  5. מאשרים שרוצים למחוק את מסד הנתונים ולוחצים על מחיקה.

מחיקת המכונה

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

בשורת הפקודה

gcloud spanner instances delete test-instance

שימוש במסוף Google Cloud

  1. נכנסים לדף Spanner Instances במסוף Google Cloud .

    כניסה לדף Instances

  2. לוחצים על המופע.

  3. לוחצים על Delete.

  4. מאשרים שרוצים למחוק את המופע ולוחצים על מחיקה.

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