Primeiros passos com o Cloud Spanner em Python

Objetivos

Este tutorial orienta você nas seguintes etapas do uso da biblioteca de cliente do Cloud Spanner para Python:

  • Criar uma instância e um banco de dados do Cloud Spanner.
  • Gravar, ler e executar consultas SQL em dados contidos no banco de dados.
  • Atualizar o esquema do banco de dados.
  • Atualizar dados usando uma transação de leitura e gravação.
  • Adicionar um índice secundário ao banco de dados.
  • Usar o índice para ler e executar consultas SQL nos dados.
  • Recuperar dados usando uma transação somente leitura.

Custos

Neste tutorial, usamos o Cloud Spanner, que é um componente faturável do Google Cloud. Para informações sobre o custo de utilização do Cloud Spanner, consulte Preços.

Antes de começar

  1. Conclua as etapas descritas em Configurar, que aborda a criação e a definição de um projeto padrão do Google Cloud, a ativação do faturamento, a ativação da API Cloud Spanner e a configuração do OAuth 2.0 para receber credenciais de autenticação para usar a API Cloud Spanner.
    Especificamente, certifique-se de executar gcloud auth application-default login para configurar seu ambiente de desenvolvimento local com credenciais de autenticação.

  2. Siga as instruções em Como configurar o ambiente de desenvolvimento do Python.

  3. Clone o repositório do app de amostra na máquina local:

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

    Outra opção é fazer o download da amostra como um arquivo zip e extraí-lo.

  4. Altere para o diretório que contém o código de amostra do Cloud Spanner:

    cd python-docs-samples/spanner/cloud-client
    
  5. Crie um ambiente Python isolado e instale as dependências:

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

Criar uma instância

Ao usar o Cloud Spanner pela primeira vez, é necessário criar uma instância, que é uma alocação de recursos usados pelos bancos de dados do Cloud Spanner. Ao criar uma instância, escolha uma configuração de instância que determine onde os dados serão armazenados e também o número de nós a serem usados. Com isso, é definida a quantidade de recursos de serviço e de armazenamento na instância.

Execute o seguinte comando para criar uma instância do Cloud Spanner na região us-central1 com um nó:

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

A instância criada tem as seguintes características:

  • Código da instância: test-instance
  • Nome de exibição: Test Instance
  • Configuração da instância: regional-us-central1 (as configurações regionais armazenam dados em uma região, enquanto as configurações multirregionais distribuem dados em várias regiões. Saiba mais em Instâncias).
  • A contagem de nós é 1 (node_count corresponde à quantidade de recursos de exibição e armazenamento disponíveis para os bancos de dados na instância. Saiba mais em Contagem de nós).

Você verá:

Creating instance...done.

Ver por meio de arquivos de amostra

O repositório de amostras contém uma amostra de como usar o Cloud Spanner com o Python.

Dê uma olhada no arquivo snippets.py, que mostra como usar o Cloud Spanner. O código mostra como criar e usar um novo banco de dados. Os dados usam o esquema de exemplo exibido na página Esquema e modelo de dados.

Crie um banco de dados

Crie um banco de dados denominado example-db na instância denominada test-instance executando o seguinte comando na linha de comando.

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

Você verá:

Created database example-db on instance test-instance

Você acabou de criar um banco de dados do Cloud Spanner. Veja a seguir o código que criou o banco de dados.

def create_database(instance_id, database_id):
    """Creates a database and tables for sample data."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)

    database = instance.database(database_id, ddl_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"""
    ])

    operation = database.create()

    print('Waiting for operation to complete...')
    operation.result()

    print('Created database {} on instance {}'.format(
        database_id, instance_id))

O código também define duas tabelas, Singers e Albums, para um aplicativo básico de música. Essas tabelas são usadas em toda esta página. Caso ainda não tenha feito isso, confira o exemplo de esquema.

A próxima etapa é gravar dados no seu banco de dados.

Criar um cliente de banco de dados

Antes de fazer leituras ou gravações, é necessário criar um Client. Pense em um Client como uma conexão com o banco de dados: todas as suas interações com o Cloud Spanner precisam passar por um Client. Normalmente, você cria um Client quando seu aplicativo é iniciado, e depois reutiliza esse Client para ler, gravar e executar transações. O código a seguir mostra como criar um cliente.

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

# Instantiate a client.
spanner_client = spanner.Client()

# Your Cloud Spanner instance ID.
instance_id = 'my-instance-id'

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

# Your Cloud Spanner database ID.
database_id = 'my-database-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)

Leia mais na referência de Client.

Gravar dados com DML

É possível inserir dados usando a linguagem de manipulação de dados (DML, na sigla em inglês) em uma transação de leitura/gravação.

Use o método execute_update() para executar uma instrução DML.

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

Execute a amostra usando o argumento insert_with_dml.

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

Você verá:

4 record(s) inserted.

Gravar dados com mutações

Também é possível inserir dados usando mutações.

Grave dados usando um objeto Batch. Um objeto Batch é um contêiner para operações de mutação. Uma mutação representa uma sequência de inserções, atualizações e exclusões que o Cloud Spanner aplica atomicamente a diferentes linhas e tabelas em um banco de dados do Cloud Spanner.

O método insert() na classe Batchadiciona uma ou mais mutações de inserção ao lote. Todas as mutações em um único lote são aplicadas atomicamente.

Este código mostra como gravar dados usando mutações:

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, u'Marc', u'Richards'),
                (2, u'Catalina', u'Smith'),
                (3, u'Alice', u'Trentor'),
                (4, u'Lea', u'Martin'),
                (5, u'David', u'Lomond')])

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

    print('Inserted data.')

Execute a amostra usando o argumento insert_data.

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

Você verá:

Inserted data.

Consultar dados usando SQL

O Cloud Spanner aceita uma interface nativa de SQL para leitura de dados, que você acessa na linha de comando usando a ferramenta de linha de comando gcloud ou programaticamente usando a biblioteca de cliente do Cloud Spanner para Python.

Na linha de comando

Execute a instrução SQL a seguir para ler os valores de todas as colunas da tabela Albums:

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

O resultado será:

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

Com a biblioteca de cliente do Cloud Spanner para Python

Além de executar uma instrução SQL na linha de comando, é possível emitir a mesma instrução SQL de maneira programática usando a biblioteca de cliente do Cloud Spanner para Python.

Use o método execute_sql() de um objeto Snapshot para executar a consulta SQL. Para conseguir um objeto Snapshot, chame o método snapshot() da classe Database em uma declaração with.

Veja como emitir a consulta e acessar os dados:

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(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))

Execute a amostra usando o argumento query_data.

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

Você verá o resultado a seguir:

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

Consulta usando um parâmetro SQL

É possível usar parâmetros para incluir valores personalizados em instruções SQL. Veja um exemplo de como usar @lastName como parâmetro na cláusula WHERE para consultar registros que contêm um valor específico para LastName.

# 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(u"SingerId: {}, FirstName: {}, LastName: {}".format(*row))

Execute a amostra usando o argumento query_data_with_parameter.

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

Você verá o resultado a seguir:

SingerId: 12, FirstName: Melissa, LastName: Garcia

Ler dados usando a API de leitura

Além da interface SQL, o Cloud Spanner também é compatível com uma interface de leitura.

Use o método read() de um objeto Snapshot para ler linhas do banco de dados. Para conseguir um objeto Snapshot, chame o método snapshot() da classe Database em uma declaração with. Use um objeto KeySet para definir uma coleção de chaves e intervalos de chaves para leitura.

Veja como ler os dados:

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(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))

Execute a amostra usando o argumento read_data.

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

Você verá uma saída como:

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

Atualizar o esquema do banco de dados

Suponha que você precise adicionar uma nova coluna denominada MarketingBudget à tabela Albums. Para isso, é necessário atualizar seu esquema de banco de dados. O Cloud Spanner é compatível com atualizações de esquema em um banco de dados enquanto esse banco continua a disponibilizar o tráfego. Para fazer atualizações no esquema, não é necessário desconectar o banco de dados, nem bloquear tabelas ou colunas inteiras. É possível continuar gravando dados no banco de dados durante a atualização do esquema. Leia mais sobre as atualizações de esquemas compatíveis e o desempenho das alterações de esquemas em Atualizações de esquema.

Adicionar uma coluna

É possível adicionar uma coluna na linha de comando usando a ferramenta de linha de comando gcloud ou programaticamente usando a biblioteca de cliente do Cloud Spanner para Python.

Na linha de comando

Use o seguinte comando ALTER TABLE para adicionar a nova coluna à tabela:

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

Você verá:

Schema updating...done.

Com a biblioteca de cliente do Cloud Spanner para Python

Use o método update_ddl() da classe Database para modificar o esquema:

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

    operation = database.update_ddl([
        'ALTER TABLE Albums ADD COLUMN MarketingBudget INT64'])

    print('Waiting for operation to complete...')
    operation.result()

    print('Added the MarketingBudget column.')

Execute a amostra usando o argumento add_column.

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

Você verá:

Added the MarketingBudget column.

Gravar dados na nova coluna

O código a seguir grava dados na coluna nova. Ele define MarketingBudget como 100000 para a linha indexada por Albums(1, 1) e como 500000 para a linha indexada por Albums(2, 2).

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.')

Execute a amostra usando o argumento update_data.

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

Também é possível executar uma consulta SQL ou uma chamada de leitura para coletar os valores que você acabou de gravar.

Veja a seguir o código para executar a consulta:

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(
                u'SingerId: {}, AlbumId: {}, MarketingBudget: {}'.format(*row))

Para executar essa consulta, execute a amostra usando o argumento query_data_with_new_column.

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

Você verá:

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

Atualizar dados

É possível atualizar dados usando DML em uma transação de leitura/gravação.

Use o método execute_update() para executar uma instrução DML.

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

Execute a amostra usando o argumento write_with_dml_transaction.

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

Você verá:

Transferred 200000 from Album2's budget to Album1's

Usar um índice secundário

Suponha que você queira buscar todas as linhas de Albums que tenham valores AlbumTitle em um determinado intervalo. É possível ler todos os valores da coluna AlbumTitle usando uma instrução SQL ou uma chamada de leitura e descartar as linhas que não satisfazem os critérios, mas fazer essa verificação na tabela inteira é caro, especialmente para tabelas com muitas linhas. Em vez disso, acelere a recuperação de linhas ao pesquisar por colunas de chaves não primárias por meio da criação de um índice secundário na tabela.

Adicionar um índice secundário a uma tabela requer uma atualização de esquema. Como outras atualizações de esquema, o Cloud Spanner é compatível com a adição de um índice enquanto o banco de dados continua a disponibilizar o tráfego. O Cloud Spanner preenche automaticamente o índice com seus dados atuais. Os preenchimentos podem levar alguns minutos para serem concluídos, mas você não precisa ficar off-line ou evitar gravar na tabela indexada durante esse processo. Para mais detalhes, consulte o preenchimento de índices.

Depois que você adiciona um índice secundário, o Cloud Spanner o usa automaticamente para consultas SQL que provavelmente serão executadas mais rapidamente com o índice. Se você usar a interface de leitura, deverá especificar o índice que quer usar.

Adicionar um índice secundário

É possível adicionar um índice na linha de comando usando a ferramenta de linha de comando gcloud ou programaticamente usando a biblioteca de cliente do Cloud Spanner para Python.

Na linha de comando

Use o comando CREATE INDEX para adicionar um índice ao banco de dados:

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

Você verá:

Schema updating...done.

Com a biblioteca de cliente do Cloud Spanner para Python

Use o método update_ddl() da classe Database para adicionar um índice:

def add_index(instance_id, database_id):
    """Adds a simple index to the example database."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    operation = database.update_ddl([
        'CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)'])

    print('Waiting for operation to complete...')
    operation.result()

    print('Added the AlbumsByAlbumTitle index.')

Execute a amostra usando o argumento add_index.

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

A adição do índice pode levar alguns minutos. Depois da adição, você verá:

Added the AlbumsByAlbumTitle index.

Ler usando o índice

Para consultas SQL, o Cloud Spanner usa automaticamente um índice apropriado. Na interface de leitura, você precisa especificar o índice em sua solicitação.

Para usar o índice na interface de leitura, forneça um argumento Index para o método read() de um objeto Snapshot. Para conseguir um objeto Snapshot, chame o método snapshot() da classe Database em uma declaração with.

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

Execute a amostra usando o argumento read_data_with_index.

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

Você verá:

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

Adicionar um índice com uma cláusula STORING

Talvez você tenha percebido que o exemplo de leitura acima não incluiu a leitura da coluna MarketingBudget. Isso ocorre porque a interface de leitura do Cloud Spanner não é compatível com a capacidade de fazer a junção de um índice a uma tabela de dados para pesquisar valores que não estão armazenados no índice.

Crie uma definição alternativa de AlbumsByAlbumTitle que armazene uma cópia de MarketingBudget no índice.

Na linha de comando

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

A adição do índice pode levar alguns minutos. Depois da adição, você verá:

Schema updating...done.

Com a biblioteca de cliente do Cloud Spanner para Python

Use o método update_ddl() da classe Database para adicionar um índice com uma cláusula STORING:

def add_storing_index(instance_id, database_id):
    """Adds an storing index to the example database."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    operation = database.update_ddl([
        'CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)'
        'STORING (MarketingBudget)'])

    print('Waiting for operation to complete...')
    operation.result()

    print('Added the AlbumsByAlbumTitle2 index.')

Execute a amostra usando o argumento add_storing_index.

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

Você verá:

Added the AlbumsByAlbumTitle2 index.

Agora é possível executar uma leitura que busque todas as colunas AlbumId, AlbumTitle e MarketingBudget do índice AlbumsByAlbumTitle2:

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_soring_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(
                u'AlbumId: {}, AlbumTitle: {}, '
                'MarketingBudget: {}'.format(*row))

Execute a amostra usando o argumento read_data_with_storing_index.

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

Você verá uma saída como:

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

Recuperar dados usando transações somente leitura

Suponha que você queira executar mais de uma leitura no mesmo carimbo de data/hora. As transações somente leitura observam um prefixo consistente do histórico de confirmações da transação. Portanto, o aplicativo sempre recebe dados consistentes. Use um objeto Snapshot para executar transações somente leitura. Para conseguir um objeto Snapshot, chame o método snapshot() da classe Database em uma declaração with.

Veja a seguir como executar uma consulta e fazer uma leitura na mesma transação somente leitura.

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(u'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(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))

Execute a amostra usando o argumento read_only_transaction.

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

Você verá uma saída como:

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

Limpar

Para não incorrer em cobranças extras na sua conta do Google Cloud pelos recursos usados neste tutorial, suspenda o banco de dados e exclua a instância que você criou.

Excluir o banco de dados

Se você excluir uma instância, todos os bancos de dados nela serão excluídos automaticamente. Nesta etapa, mostramos como excluir um banco de dados sem remover a instância. Ainda pode haver cobrança em relação à instância.

Na linha de comando

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

No Console do Cloud

  1. Acesse a página instâncias do Cloud Spanner no Console do Google Cloud.

    Acessar a página "Instâncias"

  2. Clique na instância.

  3. Clique no banco de dados que você quer excluir.

  4. Na página Detalhes do banco de dados, clique em Excluir.

  5. Confirme se quer excluir o banco de dados e clique em Excluir.

Excluir a instância

A exclusão de uma instância descarta automaticamente todos os bancos de dados criados nela.

Na linha de comando

gcloud spanner instances delete test-instance

No Console do Cloud

  1. Acesse a página instâncias do Cloud Spanner no Console do Google Cloud.

    Acessar a página "Instâncias"

  2. Clique na sua instância.

  3. Clique em Excluir.

  4. Confirme se quer excluir a instância e clique em Excluir.

A seguir

  • Acesse o Cloud Spanner em uma instância de máquina virtual: crie uma instância de máquina virtual com acesso ao seu banco de dados do Cloud Spanner.
  • Saiba mais sobre credenciais de autorização e autenticação em Primeiros passos da autenticação.
  • Saiba mais sobre os conceitos do Cloud Spanner.