Erste Schritte mit Spanner in Python


Lernziele

In dieser Anleitung werden Sie durch die folgenden Schritte mit der Spanner-Clientbibliothek für Python geführt:

  • Spanner-Instanz und -Datenbank erstellen
  • SQL-Abfragen für Daten in der Datenbank schreiben, lesen und ausführen
  • Datenbankschema aktualisieren
  • Daten mit einer Lese-Schreib-Transaktion aktualisieren
  • Sekundären Index für die Datenbank hinzufügen
  • Mit dem Index Daten lesen und SQL-Abfragen ausführen
  • Daten über eine schreibgeschützte Transaktion abrufen

Kosten

In dieser Anleitung wird Spanner verwendet, eine kostenpflichtige Komponente von Google Cloud. Informationen zu den Kosten für die Verwendung von Spanner finden Sie unter Preise.

Hinweise

Führen Sie die unter Einrichten beschriebenen Schritte aus, die das Erstellen und Festlegen eines standardmäßigen Google Cloud-Projekts, das Aktivieren der Rechnungsstellung, das Aktivieren der Cloud Spanner API und das Einrichten von OAuth 2.0 umfassen, um Anmeldedaten für die Authentifizierung für die Verwendung der Cloud Spanner API zu erhalten.

Sie müssen insbesondere gcloud auth application-default login ausführen, um die lokale Entwicklungsumgebung mit Anmeldedaten für die Authentifizierung einzurichten.

Lokale Python-Umgebung vorbereiten

  1. Folgen Sie der Anleitung unter Python-Entwicklungsumgebung einrichten.

  2. Klonen Sie das Repository der Beispiel-App auf Ihren lokalen Computer:

    git clone https://github.com/googleapis/python-spanner
    

    Sie können das Beispiel auch als ZIP-Datei herunterladen und extrahieren.

  3. Wechseln Sie in das Verzeichnis, das den Spanner-Beispielcode enthält:

    cd python-spanner/samples/samples
    
  4. Erstellen Sie eine isolierte Python-Umgebung und installieren Sie Abhängigkeiten:

    virtualenv env
    source env/bin/activate
    pip install -r requirements.txt
    

Instanz erstellen

Wenn Sie Spanner zum ersten Mal verwenden, müssen Sie eine Instanz erstellen. Dabei handelt es sich um eine Zuweisung von Ressourcen, die von Spanner-Datenbanken verwendet werden. Wenn Sie eine Instanz erstellen, müssen Sie eine Instanzkonfiguration auswählen. Abhängig davon werden der Speicherort Ihrer Daten sowie die Anzahl der zu verwendenden Knoten festgelegt. Anhand der Knotenanzahl wird dann die Menge der Bereitstellungs- und Speicherressourcen in Ihrer Instanz festgelegt.

Führen Sie den folgenden Befehl aus, um eine Spanner-Instanz in der Region us-central1 mit 1 Knoten zu erstellen:

gcloud spanner instances create test-instance --config=regional-us-central1 \
    --description="Test Instance" --nodes=1

Dadurch wird eine Instanz mit diesen Properties erstellt:

  • Instanz-ID test-instance
  • Anzeigename Test Instance
  • Instanzkonfiguration regional-us-central1 – Bei regionalen Konfigurationen werden Daten in nur einer Region gespeichert, während sie bei multiregionalen Konfigurationen auf mehrere Regionen verteilt werden. Weitere Informationen finden Sie unter Informationen zu Instanzen.
  • Knotenanzahl 1 – node_count entspricht der Anzahl der Bereitstellungs- und Speicherressourcen in der Instanz, die für Datenbanken zur Verfügung stehen. Weitere Informationen finden Sie unter Knoten und Verarbeitungseinheiten.)

Hier sollten Sie das sehen:

Creating instance...done.

Beispieldateien ansehen

Das Beispiel-Repository enthält ein Beispiel, das zeigt, wie Spanner mit Python verwendet wird.

Sehen Sie sich die Datei snippets.py an. Darin wird die Verwendung von Spanner erläutert. Der Code zeigt, wie eine neue Datenbank erstellt und verwendet wird. In den Daten wird das Beispielschema verwendet, das auf der Seite Schema und Datenmodell dargestellt ist.

Datenbank erstellen

Erstellen Sie eine Datenbank mit dem Namen example-db in der Instanz test-instance. Führen Sie dazu folgenden Befehl in der Befehlszeile aus:

python snippets.py test-instance --database-id example-db create_database

Hier sollten Sie das sehen:

Created database example-db on instance test-instance

Mit dem folgenden Code werden eine Datenbank und zwei Tabellen in der Datenbank erstellt.

def create_database(instance_id, database_id):
    """Creates a database and tables for sample data."""
    from google.cloud.spanner_admin_database_v1.types import \
        spanner_database_admin

    spanner_client = spanner.Client()
    database_admin_api = spanner_client.database_admin_api

    request = spanner_database_admin.CreateDatabaseRequest(
        parent=database_admin_api.instance_path(spanner_client.project, instance_id),
        create_statement=f"CREATE DATABASE `{database_id}`",
        extra_statements=[
            """CREATE TABLE Singers (
            SingerId     INT64 NOT NULL,
            FirstName    STRING(1024),
            LastName     STRING(1024),
            SingerInfo   BYTES(MAX),
            FullName   STRING(2048) AS (
                ARRAY_TO_STRING([FirstName, LastName], " ")
            ) STORED
        ) 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""",
        ],
    )

    operation = database_admin_api.create_database(request=request)

    print("Waiting for operation to complete...")
    database = operation.result(OPERATION_TIMEOUT_SECONDS)

    print(
        "Created database {} on instance {}".format(
            database.name,
            database_admin_api.instance_path(spanner_client.project, instance_id),
        )
    )

Im nächsten Schritt werden Daten in die Datenbank geschrieben.

Datenbankclient erstellen

Zum Ausführen von Lese- oder Schreibvorgängen müssen Sie einen Client erstellen. Sie können sich ein Client wie eine Datenbankverbindung vorstellen: Alle Interaktionen mit Spanner müssen einen Client durchlaufen. In der Regel erstellen Sie beim Starten Ihrer Anwendung einen Client. Anschließend verwenden Sie den Client zum Lesen, Schreiben und Ausführen von Transaktionen. Der folgende Code zeigt das Erstellen eines Clients.

# Imports the Google Cloud Client Library.
from google.cloud import spanner

# Your Cloud Spanner instance ID.
# instance_id = "my-instance-id"
#
# Your Cloud Spanner database ID.
# database_id = "my-database-id"
# Instantiate a client.
spanner_client = spanner.Client()

# Get a Cloud Spanner instance by ID.
instance = spanner_client.instance(instance_id)

# Get a Cloud Spanner database by ID.
database = instance.database(database_id)

# Execute a simple SQL statement.
with database.snapshot() as snapshot:
    results = snapshot.execute_sql("SELECT 1")

    for row in results:
        print(row)

Weitere Informationen finden Sie in der Referenz zu Client.

Daten mit DML schreiben

Sie können Daten mit der Datenbearbeitungssprache (Data Manipulation Language, DML) in eine Lese-Schreib-Transaktion einfügen.

Für das Ausführen einer DML-Anweisung verwenden Sie die Methode execute_update().

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

def insert_singers(transaction):
    row_ct = transaction.execute_update(
        "INSERT INTO Singers (SingerId, FirstName, LastName) VALUES "
        "(12, 'Melissa', 'Garcia'), "
        "(13, 'Russell', 'Morales'), "
        "(14, 'Jacqueline', 'Long'), "
        "(15, 'Dylan', 'Shaw')"
    )
    print("{} record(s) inserted.".format(row_ct))

database.run_in_transaction(insert_singers)

Führen Sie das Beispiel mit dem Argument insert_with_dml aus.

python snippets.py test-instance --database-id example-db insert_with_dml

Hier sollten Sie das sehen:

4 record(s) inserted.

Daten mit Mutationen schreiben

Sie können Daten auch mithilfe von Mutationen einfügen.

Daten werden mit einem Batch-Objekt geschrieben. Ein Batch-Objekt ist ein Container für Mutationsvorgänge. Eine Mutation stellt eine Folge von Einfügungs-, Aktualisierungs- und Löschvorgängen dar, die Spanner in kleinstmöglichen Schritten auf verschiedene Zeilen und Tabellen in einer Spanner-Datenbank anwendet.

Mit der Methode insert() in der Klasse Batch werden dem Batch eine oder mehrere Einfügemutationen hinzugefügt. Alle Mutationen in einem einzelnen Batch werden in kleinstmöglichen Schritten angewendet.

Dieser Code zeigt, wie die Daten mithilfe von Mutationen geschrieben werden:

def insert_data(instance_id, database_id):
    """Inserts sample data into the given database.

    The database and table must already exist and can be created using
    `create_database`.
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.batch() as batch:
        batch.insert(
            table="Singers",
            columns=("SingerId", "FirstName", "LastName"),
            values=[
                (1, "Marc", "Richards"),
                (2, "Catalina", "Smith"),
                (3, "Alice", "Trentor"),
                (4, "Lea", "Martin"),
                (5, "David", "Lomond"),
            ],
        )

        batch.insert(
            table="Albums",
            columns=("SingerId", "AlbumId", "AlbumTitle"),
            values=[
                (1, 1, "Total Junk"),
                (1, 2, "Go, Go, Go"),
                (2, 1, "Green"),
                (2, 2, "Forever Hold Your Peace"),
                (2, 3, "Terrified"),
            ],
        )

    print("Inserted data.")

Führen Sie das Beispiel mit dem Argument insert_data aus.

python snippets.py test-instance --database-id example-db insert_data

Hier sollten Sie das sehen:

Inserted data.

Daten mit SQL abfragen

Spanner unterstützt eine SQL-Schnittstelle zum Lesen von Daten, auf die Sie mit der Google Cloud CLI in der Befehlszeile oder programmgesteuert mit der Spanner-Clientbibliothek für Python zugreifen können.

Über die Befehlszeile

Führen Sie die folgende SQL-Anweisung aus, damit Sie die Werte aller Spalten aus der Tabelle Albums lesen können:

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

Das Ergebnis sollte in etwa so aussehen:

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-Clientbibliothek für Python verwenden

Als Alternative zum Ausführen einer SQL-Anweisung in der Befehlszeile können Sie die gleiche SQL-Anweisung programmatisch mithilfe der Spanner-Clientbibliothek für Python ausführen.

Verwenden Sie für das Ausführen der SQL-Abfrage die Methode execute_sql() eines Snapshot-Objekts. Für das Abrufen eines Snapshot-Objekts nutzen Sie die Methode snapshot() der Klasse Database in einer with-Anweisung.

So geben Sie die Abfrage aus und greifen auf die Daten zu:

def query_data(instance_id, database_id):
    """Queries sample data from the database using SQL."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot() as snapshot:
        results = snapshot.execute_sql(
            "SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
        )

        for row in results:
            print("SingerId: {}, AlbumId: {}, AlbumTitle: {}".format(*row))

Führen Sie das Beispiel mit dem Argument query_data aus.

python snippets.py test-instance --database-id example-db query_data

Sie sollten folgendes Ergebnis sehen:

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

Abfrage mit einem SQL-Parameter

Wenn es für Ihre Anwendung eine häufig ausgeführte Abfrage gibt, können Sie die Leistung durch Parametrieren verbessern. Die resultierende parametrische Abfrage kann im Cache gespeichert und wiederverwendet werden, wodurch die Kompilierungskosten reduziert werden. Weitere Informationen finden Sie unter Mit Abfrageparametern häufig ausgeführte Abfragen beschleunigen.

Im folgenden Beispiel wird ein Parameter in der WHERE-Klausel verwendet, um Datensätze abzufragen, die einen bestimmten Wert für LastName enthalten.

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

with database.snapshot() as snapshot:
    results = snapshot.execute_sql(
        "SELECT SingerId, FirstName, LastName FROM Singers "
        "WHERE LastName = @lastName",
        params={"lastName": "Garcia"},
        param_types={"lastName": spanner.param_types.STRING},
    )

    for row in results:
        print("SingerId: {}, FirstName: {}, LastName: {}".format(*row))

Führen Sie das Beispiel mit dem Argument query_data_with_parameter aus.

python snippets.py test-instance --database-id example-db query_data_with_parameter

Es sollte das folgende Ergebnis angezeigt werden:

SingerId: 12, FirstName: Melissa, LastName: Garcia

Daten mit der Lese-API auslesen

Zusätzlich zur SQL-Schnittstelle unterstützt Spanner auch eine Leseschnittstelle.

Verwenden Sie zum Lesen von Zeilen aus der Datenbank die Methode read() eines Snapshot-Objekts. Für den Abruf eines Snapshot-Objekts nutzen Sie die Methode snapshot() der Klasse Database in einer with-Anweisung. Mit dem Objekt KeySet können Sie eine Sammlung der Schlüssel und Schlüsselbereiche definieren, die gelesen werden sollen.

So lesen Sie die Daten aus:

def read_data(instance_id, database_id):
    """Reads sample data from the database."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot() as snapshot:
        keyset = spanner.KeySet(all_=True)
        results = snapshot.read(
            table="Albums", columns=("SingerId", "AlbumId", "AlbumTitle"), keyset=keyset
        )

        for row in results:
            print("SingerId: {}, AlbumId: {}, AlbumTitle: {}".format(*row))

Führen Sie das Beispiel mit dem Argument read_data aus.

python snippets.py test-instance --database-id example-db read_data

Die Ausgabe sollte etwa so aussehen:

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

Datenbankschema aktualisieren

Beispiel: Sie müssen eine neue Spalte namens MarketingBudget zur Tabelle Albums hinzufügen. Damit einer vorhandenen Tabelle eine neue Spalte hinzugefügt werden kann, muss das Datenbankschema aktualisiert werden. Spanner unterstützt Schemaaktualisierungen für eine Datenbank, während die Datenbank weiterhin Traffic bereitstellt. Bei Schemaaktualisierungen muss die Datenbank nicht offline geschaltet werden und es müssen keine ganzen Tabellen oder Spalten gesperrt werden. Sie können während der Schemaaktualisierung weiter Daten in die Datenbank schreiben. Weitere Informationen zu unterstützten Schemaaktualisierungen und zur Leistung während der Schemaänderung finden Sie unter Schemaaktualisierungen vornehmen.

Spalte hinzufügen

Sie können eine Spalte in der Befehlszeile mithilfe der Google Cloud CLI oder programmatisch mithilfe der Spanner-Clientbibliothek für Python hinzufügen.

Über die Befehlszeile

Verwenden Sie den folgenden Befehl ALTER TABLE, um die neue Spalte zur Tabelle hinzuzufügen:

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'

Hier sollten Sie das sehen:

Schema updating...done.

Spanner-Clientbibliothek für Python verwenden

Verwenden Sie die Methode update_ddl() der Klasse Database, um das Schema zu ändern:

def add_column(instance_id, database_id):
    """Adds a new column to the Albums table in the example database."""

    from google.cloud.spanner_admin_database_v1.types import \
        spanner_database_admin

    spanner_client = spanner.Client()
    database_admin_api = spanner_client.database_admin_api

    request = spanner_database_admin.UpdateDatabaseDdlRequest(
        database=database_admin_api.database_path(
            spanner_client.project, instance_id, database_id
        ),
        statements=[
            "ALTER TABLE Albums ADD COLUMN MarketingBudget INT64",
        ],
    )

    operation = database_admin_api.update_database_ddl(request)

    print("Waiting for operation to complete...")
    operation.result(OPERATION_TIMEOUT_SECONDS)
    print("Added the MarketingBudget column.")

Führen Sie das Beispiel mit dem Argument add_column aus.

python snippets.py test-instance --database-id example-db add_column

Hier sollten Sie das sehen:

Added the MarketingBudget column.

Daten in die neue Spalte schreiben

Mit dem folgenden Code werden Daten in die neue Spalte geschrieben. Er legt für MarketingBudget den Wert 100000 für den Zeilenschlüssel fest, der durch Albums(1, 1) angegeben wird, und 500000 für den Zeilenschlüssel, der durch Albums(2, 2) angegeben wird.

def update_data(instance_id, database_id):
    """Updates sample data in the database.

    This updates the `MarketingBudget` column which must be created before
    running this sample. You can add the column by running the `add_column`
    sample or by running this DDL statement against your database:

        ALTER TABLE Albums ADD COLUMN MarketingBudget INT64

    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.batch() as batch:
        batch.update(
            table="Albums",
            columns=("SingerId", "AlbumId", "MarketingBudget"),
            values=[(1, 1, 100000), (2, 2, 500000)],
        )

    print("Updated data.")

Führen Sie das Beispiel mit dem Argument update_data aus.

python snippets.py test-instance --database-id example-db update_data

Sie können auch eine SQL-Abfrage oder einen Leseaufruf ausführen, um die Werte abzurufen, die Sie gerade geschrieben haben.

Mit diesem Code können Sie die Abfrage ausführen:

def query_data_with_new_column(instance_id, database_id):
    """Queries sample data from the database using SQL.

    This sample uses the `MarketingBudget` column. You can add the column
    by running the `add_column` sample or by running this DDL statement against
    your database:

        ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot() as snapshot:
        results = snapshot.execute_sql(
            "SELECT SingerId, AlbumId, MarketingBudget FROM Albums"
        )

        for row in results:
            print("SingerId: {}, AlbumId: {}, MarketingBudget: {}".format(*row))

Für diese Abfrage führen Sie das Beispiel mit dem Argument query_data_with_new_column aus.

python snippets.py test-instance --database-id example-db query_data_with_new_column

Hier sollten Sie das sehen:

SingerId: 2, AlbumId: 2, MarketingBudget: 500000
SingerId: 1, AlbumId: 2, MarketingBudget: None
SingerId: 2, AlbumId: 1, MarketingBudget: None
SingerId: 2, AlbumId: 3, MarketingBudget: None
SingerId: 1, AlbumId: 1, MarketingBudget: 100000

Daten aktualisieren

Sie können Daten mit DML in einer Lese-Schreib-Transaktion aktualisieren.

Für das Ausführen einer DML-Anweisung verwenden Sie die Methode execute_update().

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"

spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

def transfer_budget(transaction):
    # Transfer marketing budget from one album to another. Performed in a
    # single transaction to ensure that the transfer is atomic.
    second_album_result = transaction.execute_sql(
        "SELECT MarketingBudget from Albums " "WHERE SingerId = 2 and AlbumId = 2"
    )
    second_album_row = list(second_album_result)[0]
    second_album_budget = second_album_row[0]

    transfer_amount = 200000

    # Transaction will only be committed if this condition still holds at
    # the time of commit. Otherwise it will be aborted and the callable
    # will be rerun by the client library
    if second_album_budget >= transfer_amount:
        first_album_result = transaction.execute_sql(
            "SELECT MarketingBudget from Albums "
            "WHERE SingerId = 1 and AlbumId = 1"
        )
        first_album_row = list(first_album_result)[0]
        first_album_budget = first_album_row[0]

        second_album_budget -= transfer_amount
        first_album_budget += transfer_amount

        # Update first album
        transaction.execute_update(
            "UPDATE Albums "
            "SET MarketingBudget = @AlbumBudget "
            "WHERE SingerId = 1 and AlbumId = 1",
            params={"AlbumBudget": first_album_budget},
            param_types={"AlbumBudget": spanner.param_types.INT64},
        )

        # Update second album
        transaction.execute_update(
            "UPDATE Albums "
            "SET MarketingBudget = @AlbumBudget "
            "WHERE SingerId = 2 and AlbumId = 2",
            params={"AlbumBudget": second_album_budget},
            param_types={"AlbumBudget": spanner.param_types.INT64},
        )

        print(
            "Transferred {} from Album2's budget to Album1's".format(
                transfer_amount
            )
        )

database.run_in_transaction(transfer_budget)

Führen Sie das Beispiel mit dem Argument write_with_dml_transaction aus.

python snippets.py test-instance --database-id example-db write_with_dml_transaction

Hier sollten Sie das sehen:

Transferred 200000 from Album2's budget to Album1's

Sekundären Index verwenden

Beispiel: Sie möchten alle Zeilen aus Albums abrufen, deren Wert für AlbumTitle in einem bestimmten Bereich liegen. Sie könnten dazu alle Werte aus der Spalte AlbumTitle mit einer SQL-Anweisung oder einem Leseaufruf lesen und dann die Zeilen verwerfen, die die Kriterien nicht erfüllen. Dieser vollständige Tabellenscan wäre jedoch sehr kostspielig, insbesondere bei Tabellen mit vielen Zeilen. Stattdessen können Sie einen sekundären Index für die Tabelle erstellen und damit das Abrufen von Zeilen beim Suchen über Spalten mit nicht primärem Schlüssel beschleunigen.

Damit ein sekundärer Index einer vorhandenen Tabelle hinzugefügt werden kann, muss das Schema aktualisiert werden. Wie bei anderen Schemaaktualisierungen unterstützt Spanner das Hinzufügen eines Index, während die Datenbank weiterhin Traffic verarbeitet. Spanner füllt den Index automatisch mit Ihren vorhandenen Daten auf. Backfills können einige Minuten dauern. Sie müssen aber die Datenbank nicht offline schalten und können während des Vorgangs weiter in die indexierten Tabellen schreiben. Weitere Informationen finden Sie unter Sekundären Index hinzufügen.

Nachdem Sie einen sekundären Index hinzugefügt haben, verwendet Spanner ihn automatisch für SQL-Abfragen, die mit dem Index wahrscheinlich schneller ausgeführt werden. Wenn Sie die Leseschnittstelle verwenden, müssen Sie den Index angeben, den Sie nutzen möchten.

Sekundären Index hinzufügen

Sie können einen Index mit der gcloud CLI in der Befehlszeile oder programmgesteuert über die Spanner-Clientbibliothek für Python hinzufügen.

Über die Befehlszeile

Verwenden Sie den folgenden Befehl CREATE INDEX, um der Datenbank einen Index hinzuzufügen:

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

Hier sollten Sie das sehen:

Schema updating...done.

Spanner-Clientbibliothek für Python verwenden

Verwenden Sie die Methode update_ddl() der Klasse Database, um einen Index hinzuzufügen:

def add_index(instance_id, database_id):
    """Adds a simple index to the example database."""

    from google.cloud.spanner_admin_database_v1.types import \
        spanner_database_admin

    spanner_client = spanner.Client()
    database_admin_api = spanner_client.database_admin_api

    request = spanner_database_admin.UpdateDatabaseDdlRequest(
        database=database_admin_api.database_path(
            spanner_client.project, instance_id, database_id
        ),
        statements=["CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"],
    )

    operation = database_admin_api.update_database_ddl(request)

    print("Waiting for operation to complete...")
    operation.result(OPERATION_TIMEOUT_SECONDS)

    print("Added the AlbumsByAlbumTitle index.")

Führen Sie das Beispiel mit dem Argument add_index aus.

python snippets.py test-instance --database-id example-db add_index

Das Hinzufügen eines Index kann einige Minuten dauern. Nachdem der Index hinzugefügt wurde, sollten Sie das sehen:

Added the AlbumsByAlbumTitle index.

Mit dem Index auslesen

Für SQL-Abfragen verwendet Spanner automatisch einen geeigneten Index. In der Leseschnittstelle müssen Sie den Index in Ihrer Anfrage angeben.

Für die Verwendung des Index in der Leseschnittstelle geben Sie mit der Methode read() eines Snapshot-Objekts ein Index-Argument an. Für den Abruf eines Snapshot-Objekts verwenden Sie die Methode snapshot() der Klasse Database in einer with-Anweisung.

def read_data_with_index(instance_id, database_id):
    """Reads sample data from the database using an index.

    The index must exist before running this sample. You can add the index
    by running the `add_index` sample or by running this DDL statement against
    your database:

        CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)

    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot() as snapshot:
        keyset = spanner.KeySet(all_=True)
        results = snapshot.read(
            table="Albums",
            columns=("AlbumId", "AlbumTitle"),
            keyset=keyset,
            index="AlbumsByAlbumTitle",
        )

        for row in results:
            print("AlbumId: {}, AlbumTitle: {}".format(*row))

Führen Sie das Beispiel mit dem Argument read_data_with_index aus.

python snippets.py test-instance --database-id example-db read_data_with_index

Hier sollten Sie das sehen:

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

Index für reine Indexlesevorgänge hinzufügen

Vielleicht haben Sie bemerkt, dass im vorherigen Lesebeispiel das Lesen der Spalte MarketingBudget nicht enthalten ist. Das liegt daran, dass die Leseschnittstelle von Spanner die Möglichkeit, einen Index mit einer Datentabelle zu verknüpfen, nicht unterstützt, um nach Werten zu suchen, die nicht im Index gespeichert sind.

Erstellen Sie eine alternative Definition von AlbumsByAlbumTitle, die eine Kopie von MarketingBudget im Index speichert.

Über die Befehlszeile

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)

Das Hinzufügen eines Index kann einige Minuten dauern. Nachdem der Index hinzugefügt wurde, sollte Folgendes angezeigt werden:

Schema updating...done.

Spanner-Clientbibliothek für Python verwenden

Verwenden Sie die Methode update_ddl() der Klasse Database, um einen Index mit einer STORING-Klausel hinzuzufügen:

def add_storing_index(instance_id, database_id):
    """Adds an storing index to the example database."""

    from google.cloud.spanner_admin_database_v1.types import \
        spanner_database_admin

    spanner_client = spanner.Client()
    database_admin_api = spanner_client.database_admin_api

    request = spanner_database_admin.UpdateDatabaseDdlRequest(
        database=database_admin_api.database_path(
            spanner_client.project, instance_id, database_id
        ),
        statements=[
            "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)"
            "STORING (MarketingBudget)"
        ],
    )

    operation = database_admin_api.update_database_ddl(request)

    print("Waiting for operation to complete...")
    operation.result(OPERATION_TIMEOUT_SECONDS)

    print("Added the AlbumsByAlbumTitle2 index.")

Führen Sie das Beispiel mit dem Argument add_storing_index aus.

python snippets.py test-instance --database-id example-db add_storing_index

Hier sollten Sie dies sehen:

Added the AlbumsByAlbumTitle2 index.

Sie können jetzt einen Lesevorgang ausführen, der die Spalten AlbumId, AlbumTitle und MarketingBudget aus dem Index AlbumsByAlbumTitle2 abruft:

def read_data_with_storing_index(instance_id, database_id):
    """Reads sample data from the database using an index with a storing
    clause.

    The index must exist before running this sample. You can add the index
    by running the `add_scoring_index` sample or by running this DDL statement
    against your database:

        CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)
        STORING (MarketingBudget)

    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot() as snapshot:
        keyset = spanner.KeySet(all_=True)
        results = snapshot.read(
            table="Albums",
            columns=("AlbumId", "AlbumTitle", "MarketingBudget"),
            keyset=keyset,
            index="AlbumsByAlbumTitle2",
        )

        for row in results:
            print("AlbumId: {}, AlbumTitle: {}, " "MarketingBudget: {}".format(*row))

Führen Sie das Beispiel mit dem Argument read_data_with_storing_index aus.

python snippets.py test-instance --database-id example-db read_data_with_storing_index

Die Ausgabe sollte etwa so aussehen:

AlbumId: 2, AlbumTitle: Forever Hold Your Peace, MarketingBudget: 300000
AlbumId: 2, AlbumTitle: Go, Go, Go, MarketingBudget: None
AlbumId: 1, AlbumTitle: Green, MarketingBudget: None
AlbumId: 3, AlbumTitle: Terrified, MarketingBudget: None
AlbumId: 1, AlbumTitle: Total Junk, MarketingBudget: 300000

Daten mit schreibgeschützten Transaktionen abrufen

Angenommen, Sie möchten mehr als einen Lesevorgang mit demselben Zeitstempel ausführen. Bei schreibgeschützten Transaktionen wird ein gleichbleibendes Präfix des Commit-Verlaufs der Transaktionen beibehalten, damit die Anwendung immer konsistente Daten erhält. Zum Ausführen schreibgeschützter Transaktionen verwenden Sie ein Snapshot-Objekt . Für den Abruf eines Snapshot-Objekts nutzen Sie die Methode snapshot() der Klasse Database in einer with-Anweisung.

So werden eine Abfrage und ein Lesevorgang in derselben schreibgeschützten Transaktion ausgeführt:

def read_only_transaction(instance_id, database_id):
    """Reads data inside of a read-only transaction.

    Within the read-only transaction, or "snapshot", the application sees
    consistent view of the database at a particular timestamp.
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot(multi_use=True) as snapshot:
        # Read using SQL.
        results = snapshot.execute_sql(
            "SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
        )

        print("Results from first read:")
        for row in results:
            print("SingerId: {}, AlbumId: {}, AlbumTitle: {}".format(*row))

        # Perform another read using the `read` method. Even if the data
        # is updated in-between the reads, the snapshot ensures that both
        # return the same data.
        keyset = spanner.KeySet(all_=True)
        results = snapshot.read(
            table="Albums", columns=("SingerId", "AlbumId", "AlbumTitle"), keyset=keyset
        )

        print("Results from second read:")
        for row in results:
            print("SingerId: {}, AlbumId: {}, AlbumTitle: {}".format(*row))

Führen Sie das Beispiel mit dem Argument read_only_transaction aus.

python snippets.py test-instance --database-id example-db read_only_transaction

Die Ausgabe sollte etwa so aussehen:

Results from first read:
SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold Your Peace
SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go
SingerId: 2, AlbumId: 1, AlbumTitle: Green
SingerId: 2, AlbumId: 3, AlbumTitle: Terrified
SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk
Results from second read:
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

Bereinigen

Löschen Sie die Datenbank und die erstellte Instanz, um zu vermeiden, dass Ihrem Cloud-Rechnungskonto die in dieser Anleitung verwendeten Ressourcen in Rechnung gestellt werden.

Datenbank löschen

Wenn Sie eine Instanz löschen, werden alle darin enthaltenen Datenbanken automatisch gelöscht. In diesem Schritt wird gezeigt, wie eine Datenbank gelöscht wird, ohne eine Instanz zu löschen (dabei fallen weiterhin Gebühren für die Instanz an).

Über die Befehlszeile

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

Google Cloud Console verwenden

  1. Rufen Sie in der Google Cloud Console die Seite Spanner-Instanzen auf.

    Zur Seite "VM-Instanzen"

  2. Klicken Sie auf die Instanz.

  3. Klicken Sie auf die Datenbank, die Sie löschen möchten.

  4. Klicken Sie auf der Seite Datenbankdetails auf Löschen.

  5. Bestätigen Sie, dass die Datenbank gelöscht werden soll, und klicken Sie auf Löschen.

Instanz löschen

Beim Löschen einer Instanz werden alle Datenbanken, die in der Instanz erstellt wurden, automatisch gelöscht.

Über die Befehlszeile

gcloud spanner instances delete test-instance

Google Cloud Console verwenden

  1. Rufen Sie in der Google Cloud Console die Seite Spanner-Instanzen auf.

    Zur Seite "VM-Instanzen"

  2. Klicken Sie auf die Instanz.

  3. Klicken Sie auf Löschen.

  4. Bestätigen Sie, dass die Instanz gelöscht werden soll, und klicken Sie auf Löschen.

Nächste Schritte