Começar a usar o Spanner usando a REST


Objetivos

Este tutorial apresenta as seguintes etapas usando a Cloud Spanner API com a REST:

  • Criar uma instância e um banco de dados do Spanner.
  • Gravar, ler e executar consultas SQL em dados contidos no banco de dados.
  • Atualizar o esquema do banco de dados.
  • 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.

Se você quiser usar bibliotecas de cliente do Spanner em vez de usar a API REST, consulte Tutoriais.

Custos

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

Antes de começar

  1. Faça login na sua conta do Google Cloud. Se você começou a usar o Google Cloud agora, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  3. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  4. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  5. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

Maneiras de fazer chamadas REST

É possível fazer chamadas REST do Spanner usando:

Convenções usadas nesta página

  • Os exemplos usam [PROJECT_ID] como o ID do projeto do Google Cloud. Substitua seu ID do projeto do Google Cloud por [PROJECT_ID]. (Não inclua [ e ] no código do projeto.)

  • Os exemplos criam e usam um código de instância de test-instance. Substitua o código da instância se você não estiver usando test-instance.

  • Os exemplos criam e usam um código de banco de dados de example-db. Substitua o código do seu banco de dados se você não estiver usando example-db.

  • Os exemplos usam [SESSION] como parte de um nome de sessão. Substitua por [SESSION] o valor que você receber quando criar uma sessão. (Não inclua [ e ] no nome da sessão.)

  • Os exemplos usam um código de transação de [TRANSACTION_ID]. Substitua [TRANSACTION_ID] pelo valor que você receber quando criar uma transação. (Não inclua [ e ] no código da transação.)

  • A funcionalidade Faça um teste! permite a adição interativa de campos individuais de solicitação HTTP. A maioria dos exemplos neste tópico fornece toda a solicitação em vez de descrever como adicionar interativamente campos individuais.

Instâncias

Quando você usa o Spanner pela primeira vez, precisa criar uma instância, que é uma alocação de recursos usados pelos bancos de dados do Spanner. Ao criar uma instância, você escolhe onde os dados são armazenados e a capacidade de computação dela.

Listar configurações de instância

Ao criar uma instância, você especifica uma configuração de instância que define a colocação geográfica e a replicação de bancos de dados nessa instância. É possível escolher uma configuração regional, para armazenar dados em uma região ou uma configuração de várias regiões, para distribuir dados em várias regiões. Saiba mais em Instâncias.

Use projects.instanceConfigs.list para determinar quais configurações estão disponíveis para seu projeto do Google Cloud.

  1. Clique em projects.instanceConfigs.list.
  2. Para o parent, digite:

    projects/[PROJECT_ID]
    
  3. Clique em Executar. As configurações de instância disponíveis são mostradas na resposta. Veja um exemplo de resposta (seu projeto pode ter diferentes configurações de instância):

    {
      "instanceConfigs": [
        {
          "name": "projects/[PROJECT_ID]/instanceConfigs/regional-asia-south1",
          "displayName": "asia-south1"
        },
        {
          "name": "projects/[PROJECT_ID]/instanceConfigs/regional-asia-east1",
          "displayName": "asia-east1"
        },
        {
          "name": "projects/[PROJECT_ID]/instanceConfigs/regional-asia-northeast1",
          "displayName": "asia-northeast1"
        },
        {
          "name": "projects/[PROJECT_ID]/instanceConfigs/regional-europe-west1",
          "displayName": "europe-west1"
        },
        {
          "name": "projects/[PROJECT_ID]/instanceConfigs/regional-us-east4",
          "displayName": "us-east4"
        },
        {
          "name": "projects/[PROJECT_ID]/instanceConfigs/regional-us-central1",
          "displayName": "us-central1"
        }
      ]
    }
    

Você usa o valor name de uma das configurações de instância ao criar sua instância.

Criar uma instância

  1. Clique em projects.instances.create.
  2. Para o parent, digite:

    projects/[PROJECT_ID]
    
  3. Clique em Adicionar parâmetros do corpo da solicitação e selecione instance.

  4. Clique no balão da dica em Instância para ver os campos possíveis. Adicione valores para os seguintes campos:

    1. nodeCount: insira 1.
    2. config: insira o valor name de uma das configurações de instância regional retornadas quando você listar as configurações de instância.
    3. displayName: insira Test Instance.
  5. Clique no balão da dica depois do colchete de fechamento para Instância e selecione instanceId.

  6. Para instanceId, digite test-instance
    Sua a página de criação de instância terá Faça um teste! esta aparência:

    Captura de tela da criação de instância

  7. Clique em Executar. Na resposta é retornada uma operação de longa duração que pode ser consultada para verificar o status.

É possível listar suas instâncias usando projects.instances.list.

Crie um banco de dados

Crie um banco de dados chamado example-db.

  1. Clique em projects.instances.databases.create.
  2. Para o parent, digite:

    projects/[PROJECT_ID]/instances/test-instance
    
  3. Clique em Adicionar parâmetros do corpo da solicitação e selecione createStatement.

  4. Para createStatement, digite:

    CREATE DATABASE `example-db`
    

    O nome do banco de dados, example-db, contém um hífen, por isso deve estar entre acentos graves (`).

  5. Clique em Execute. Na resposta é retornada uma operação de longa duração que pode ser consultada para verificar o status.

É possível listar seus bancos de dados usando projects.instances.databases.list.

Crie um esquema

Use a linguagem de definição de dados (DDL) do Spanner para criar, alterar ou remover tabelas e criar ou remover índices.

  1. Clique em projects.instances.databases.updateDdl.
  2. Para o banco de dados, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db
    
  3. Para o Corpo de solicitação, use o seguinte:

    {
      "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"
      ]
    }
    

    A matriz statements contém as instruções DDL que definem o esquema.

  4. Clique em Execute. Na resposta é retornada uma operação de longa duração que pode ser consultada para verificar o status.

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

É possível recuperar seu esquema usando projects.instances.databases.getDdl.

Criar uma sessão

Antes de adicionar, atualizar, excluir ou consultar dados, crie uma sessão que represente um canal de comunicação com o serviço de banco de dados do Spanner. Você não usa diretamente uma sessão se estiver usando uma biblioteca de cliente do Spanner, porque a biblioteca gerencia as sessões em seu nome.

  1. Clique em projects.instances.databases.sessions.create.
  2. Para o banco de dados, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db
    
  3. Clique em Executar.

  4. A resposta mostra a sessão que você criou, no formato

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você usará esta sessão quando ler ou gravar no banco de dados.

As sessões devem ser de longa duração. O serviço de banco de dados do Spanner poderá excluir uma sessão quando ela ficar inativa por mais de uma hora. As tentativas de usar uma sessão excluída resultam em NOT_FOUND. Se você encontrar esse erro, crie e use uma nova sessão. É possível ver se uma sessão ainda está ativa usando projects.instances.databases.sessions.get. Para informações relacionadas, consulte Manter uma sessão ociosa ativa.

O próximo passo é gravar dados no seu banco de dados.

Gravar dados

Os dados são gravados usando o tipo Mutation. Um Mutation é um contêiner para operações de mutação. Um Mutation representa uma sequência de inserções, atualizações, exclusões e outras ações que podem ser aplicadas atomicamente em diferentes linhas e tabelas em um banco de dados do Spanner.

  1. Clique em projects.instances.databases.sessions.commit.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "singleUseTransaction": {
        "readWrite": {}
      },
      "mutations": [
        {
          "insertOrUpdate": {
            "table": "Singers",
            "columns": [
              "SingerId",
              "FirstName",
              "LastName"
            ],
            "values": [
              [
                "1",
                "Marc",
                "Richards"
              ],
              [
                "2",
                "Catalina",
                "Smith"
              ],
              [
                "3",
                "Alice",
                "Trentor"
              ],
              [
                "4",
                "Lea",
                "Martin"
              ],
              [
                "5",
                "David",
                "Lomond"
              ]
            ]
          }
        },
        {
          "insertOrUpdate": {
            "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"
              ]
            ]
          }
        }
      ]
    }
    
  4. Clique em Executar. A resposta mostra o carimbo de data/hora da confirmação.

Este exemplo usou insertOrUpdate. Outras operations para Mutations são insert, update, replace e delete.

Para informações sobre como codificar tipos de dados, consulte TypeCode.

Consultar dados usando SQL

  1. Clique em projects.instances.databases.sessions.executeSql.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "sql": "SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
    }
    
  4. Clique em Executar. A resposta exibe os resultados da consulta.

Ler dados usando a API de leitura

  1. Clique em projects.instances.databases.sessions.read.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "table": "Albums",
      "columns": [
        "SingerId",
        "AlbumId",
        "AlbumTitle"
      ],
      "keySet": {
        "all": true
      }
    }
    
  4. Clique em Executar. A resposta exibe os resultados de leitura.

Atualizar o esquema do banco de dados

Suponha que você precise adicionar uma nova coluna chamada MarketingBudget à tabela Albums, que requer uma atualização para seu esquema de banco de dados. O Spanner oferece suporte a atualizações de esquema para um banco de dados enquanto o banco de dados 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.

Adicionar uma coluna

  1. Clique em projects.instances.databases.updateDdl.
  2. Para o banco de dados, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db
    
  3. Para o Corpo de solicitação, use o seguinte:

    {
      "statements": [
        "ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"
      ]
    }
    

    A matriz statements contém as instruções DDL que definem o esquema.

  4. Clique em Executar. Isso pode levar alguns minutos para ser concluído, mesmo após a resposta ter sido retornada pela chamada REST. Na resposta é retornada uma operação de longa duração que pode ser consultada para verificar o status.

Gravar dados na coluna nova

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

  1. Clique em projects.instances.databases.sessions.commit.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "singleUseTransaction": {
        "readWrite": {}
      },
      "mutations": [
        {
          "update": {
            "table": "Albums",
            "columns": [
              "SingerId",
              "AlbumId",
              "MarketingBudget"
            ],
            "values": [
              [
                "1",
                "1",
                "100000"
              ],
              [
                "2",
                "2",
                "500000"
              ]
            ]
          }
        }
      ]
    }
    
  4. Clique em Executar. A resposta mostra o carimbo de data/hora da confirmação.

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

Veja como executar a consulta:

  1. Clique em projects.instances.databases.sessions.executeSql.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "sql": "SELECT SingerId, AlbumId, MarketingBudget FROM Albums"
    }
    
  4. Clique em Executar. Como parte da resposta, você deve ver duas linhas que contêm os valores MarketingBudget atualizados:

    "rows": [
      [
        "1",
        "1",
        "100000"
      ],
      [
        "1",
        "2",
        null
      ],
      [
        "2",
        "1",
        null
      ],
      [
        "2",
        "2",
        "500000"
      ],
      [
        "2",
        "3",
        null
      ]
    ]
    

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 Spanner oferece suporte à adição de um índice enquanto o banco de dados continua a disponibilizar o tráfego. O 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 em determinadas tabelas ou colunas durante esse processo. Para mais detalhes, consulte o preenchimento de índices.

Depois que você adiciona um índice secundário, o 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 usando updateDdl.

  1. Clique em projects.instances.databases.updateDdl.
  2. Para o banco de dados, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db
    
  3. Para o Corpo de solicitação, use o seguinte código:

    {
      "statements": [
        "CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"
      ]
    }
    
  4. Clique em Executar. Isso pode levar alguns minutos para ser concluído, mesmo após a resposta ter sido retornada pela chamada REST. Na resposta é retornada uma operação de longa duração que pode ser consultada para verificar o status.

Consultar usando o índice

  1. Clique em projects.instances.databases.sessions.executeSql.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "sql": "SELECT AlbumId, AlbumTitle, MarketingBudget FROM Albums WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo'"
    }
    
  4. Clique em Executar. Como parte da resposta, você verá as seguintes linhas:

    "rows": [
      [
        "2",
        "Go, Go, Go",
        null
      ],
      [
        "2",
        "Forever Hold Your Peace",
        "500000"
      ]
    ]
    

Ler usando o índice

  1. Clique em projects.instances.databases.sessions.read.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "table": "Albums",
      "columns": [
        "AlbumId",
        "AlbumTitle"
      ],
      "keySet": {
        "all": true
      },
      "index": "AlbumsByAlbumTitle"
    }
    
  4. Clique em Executar. Como parte da resposta, você deve ver as seguintes linhas:

    "rows": [
      [
        "2",
        "Forever Hold Your Peace"
      ],
      [
        "2",
        "Go, Go, Go"
      ],
      [
        "1",
        "Green"
      ],
      [
        "3",
        "Terrified"
      ],
      [
        "1",
        "Total Junk"
      ]
    ]
    

Adicionar um índice com a 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 Spanner não é compatível com a capacidade de mesclar um índice com uma tabela de dados para procurar 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.

É possível adicionar um índice STORING usando updateDdl.

  1. Clique em projects.instances.databases.updateDdl.
  2. Para o banco de dados, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db
    
  3. Para o Corpo de solicitação, use o seguinte código:

    {
      "statements": [
        "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)"
      ]
    }
    
  4. Clique em Executar. Isso pode levar alguns minutos para ser concluído, mesmo após a resposta ter sido retornada pela chamada REST. Na resposta é retornada uma operação de longa duração que pode ser consultada para verificar o status.

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

  1. Clique em projects.instances.databases.sessions.read.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "table": "Albums",
      "columns": [
        "AlbumId",
        "AlbumTitle",
        "MarketingBudget"
      ],
      "keySet": {
        "all": true
      },
      "index": "AlbumsByAlbumTitle2"
    }
    
  4. Clique em Executar. Como parte da resposta, você deve ver as seguintes linhas:

    "rows": [
      [
        "2",
        "Forever Hold Your Peace",
        "500000"
      ],
      [
        "2",
        "Go, Go, Go",
        null
      ],
      [
        "1",
        "Green",
        null
      ],
      [
        "3",
        "Terrified",
        null
      ],
      [
        "1",
        "Total Junk",
        "100000"
      ]
    ]
    

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.

Criar uma transação somente leitura

  1. Clique em projects.instances.databases.sessions.beginTransaction.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    
  3. Para o Corpo de solicitação, use o seguinte:

    {
      "options": {
        "readOnly": {}
      }
    }
    
  4. Clique em Executar.

  5. A resposta mostra o código da transação que você criou.

Agora é possível usar a transação somente leitura para recuperar dados em um carimbo de data/hora consistente, mesmo que os dados tenham mudado desde a criação da transação somente leitura.

Executar uma consulta usando a transação somente leitura

  1. Clique em projects.instances.databases.sessions.executeSql.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "sql": "SELECT SingerId, AlbumId, AlbumTitle FROM Albums",
      "transaction": {
        "id": "[TRANSACTION_ID]"
      }
    }
    
  4. Clique em Executar. Você deve ver linhas semelhantes às seguintes na resposta:

    "rows": [
      [
        "2",
        "2",
        "Forever Hold Your Peace"
      ],
      [
        "1",
        "2",
        "Go, Go, Go"
      ],
      [
        "2",
        "1",
        "Green"
      ],
      [
        "2",
        "3",
        "Terrified"
      ],
      [
        "1",
        "1",
        "Total Junk"
      ]
    ]
    

Fazer leitura usando a transação somente leitura

  1. Clique em projects.instances.databases.sessions.read.
  2. Para a sessão, digite:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
    

    Você receberá esse valor quando criar uma sessão.

  3. Para o Corpo de solicitação, use o seguinte:

    {
      "table": "Albums",
      "columns": [
        "SingerId",
        "AlbumId",
        "AlbumTitle"
      ],
      "keySet": {
        "all": true
      },
      "transaction": {
        "id": "[TRANSACTION_ID]"
      }
    }
    
  4. Clique em Executar. Você deve ver linhas semelhantes às seguintes na resposta:

    "rows": [
      [
        "1",
        "1",
        "Total Junk"
      ],
      [
        "1",
        "2",
        "Go, Go, Go"
      ],
      [
        "2",
        "1",
        "Green"
      ],
      [
        "2",
        "2",
        "Forever Hold Your Peace"
      ],
      [
        "2",
        "3",
        "Terrified"
      ]
    ]
    

O Spanner também oferece suporte a transações de leitura e gravação, que executam um conjunto de leituras e gravações atomicamente em um único ponto lógico no tempo. Para mais informações, consulte Transações de leitura e gravação (A funcionalidade Faça um teste! não é adequada para demonstrar uma transação de leitura e gravação.)

Limpeza

Para não gerar 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.

Remover um banco de dados

  1. Clique em projects.instances.databases.dropDatabase.
  2. Para o nome, insira:

    projects/[PROJECT_ID]/instances/test-instance/databases/example-db
    
  3. Clique em Executar.

Excluir uma instância

  1. Clique em projects.instances.delete.
  2. Para o nome, insira:

    projects/[PROJECT_ID]/instances/test-instance
    
  3. Clique em Executar.

A seguir