Objetivos
Este tutorial explica os seguintes passos através da API Cloud Spanner com REST:
- Crie uma instância e uma base de dados do Spanner.
- Escrever, ler e executar consultas SQL em dados na base de dados.
- Atualize o esquema da base de dados.
- Adicione um índice secundário à base de dados.
- Use o índice para ler e executar consultas SQL em dados.
- Recuperar dados através de uma transação só de leitura.
Se quiser usar as bibliotecas de cliente do Spanner em vez da API REST, consulte os tutoriais.
Custos
Este tutorial usa o Spanner, que é um componente faturável do Google Cloud. Para obter informações sobre o custo de utilização do Spanner, consulte a secção Preços.
Antes de começar
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator
(
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator
(
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
- A funcionalidade Experimente! que se encontra na documentação de referência da API Spanner. Os exemplos apresentados nesta página usam a funcionalidade Experimentar!.
- Explorador de APIs Google, que contém a API Cloud Spanner e outras APIs Google.
- Outras ferramentas ou frameworks que suportam chamadas REST HTTP.
Os exemplos usam
[PROJECT_ID]
como o Google Cloud ID do projeto. Substitua o seuGoogle Cloud ID do projeto por[PROJECT_ID]
. Não inclua[
e]
no ID do projeto.Os exemplos criam e usam um ID de instância de
test-instance
. Substitua o ID da instância se não estiver a usar otest-instance
.Os exemplos criam e usam um ID da base de dados de
example-db
. Substitua o ID da base de dados se não estiver a usarexample-db
.Os exemplos usam
[SESSION]
como parte de um nome de sessão. Substitua o valor que recebe quando cria uma sessão para[SESSION]
. (Não inclua[
e]
no nome da sessão.)Os exemplos usam um ID da transação de
[TRANSACTION_ID]
. Substitua o valor que recebe quando cria uma transação por[TRANSACTION_ID]
. (Não inclua[
e]
no ID da transação.)A funcionalidade Experimentar! suporta a adição interativa de campos de pedidos HTTP individuais. A maioria dos exemplos neste tópico fornece o pedido completo em vez de descrever como adicionar interativamente campos individuais ao pedido.
- Clique em
projects.instanceConfigs.list
. Para o publicador principal, introduza:
projects/[PROJECT_ID]
Clique em Executar. As configurações de instâncias disponíveis são apresentadas na resposta. Segue-se um exemplo de resposta (o seu projeto pode ter configurações de instância diferentes):
{ "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" } ] }
- Clique em
projects.instances.create
. Para o publicador principal, introduza:
projects/[PROJECT_ID]
Clique em Adicionar parâmetros do corpo do pedido e selecione
instance
.Clique no balão de sugestão para instance para ver os campos possíveis. Adicione valores para os seguintes campos:
nodeCount
: introduza1
.config
: introduza o valorname
de uma das configurações de instâncias regionais devolvidas quando listar as configurações de instâncias.displayName
: introduzaTest Instance
.
Clique no balão de sugestão que segue o parênteses de fecho de instance e selecione instanceId.
Para
instanceId
, introduzatest-instance
.
A página de criação da instância Experimentar! deve ter o seguinte aspeto:Clique em Executar. A resposta devolve uma operação de longa duração que pode consultar para verificar o respetivo estado.
- Clique em
projects.instances.databases.create
. Para o publicador principal, introduza:
projects/[PROJECT_ID]/instances/test-instance
Clique em Adicionar parâmetros do corpo do pedido e selecione
createStatement
.Para
createStatement
, introduza:CREATE DATABASE `example-db`
(O nome da base de dados,
example-db
, contém um hífen, pelo que tem de estar entre acentos graves (`
).Clique em Executar. A resposta devolve uma operação de longa duração que pode consultar para verificar o respetivo estado.
- Clique em
projects.instances.databases.updateDdl
. Para base de dados, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db
Para o corpo do pedido, 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 declarações DDL que definem o esquema.Clique em Executar. A resposta devolve uma operação de longa duração que pode consultar para verificar o respetivo estado.
- Clique em
projects.instances.databases.sessions.create
. Para base de dados, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db
Clique em Executar.
A resposta mostra a sessão que criou no formulário
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
Vai usar esta sessão quando ler ou escrever na sua base de dados.
- Clique em
projects.instances.databases.sessions.commit
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, 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" ] ] } } ] }
Clique em Executar. A resposta mostra a data/hora da confirmação.
- Clique em
projects.instances.databases.sessions.executeSql
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "sql": "SELECT SingerId, AlbumId, AlbumTitle FROM Albums" }
Clique em Executar. A resposta mostra os resultados da consulta.
- Clique em
projects.instances.databases.sessions.read
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "table": "Albums", "columns": [ "SingerId", "AlbumId", "AlbumTitle" ], "keySet": { "all": true } }
Clique em Executar. A resposta mostra os resultados lidos.
- Clique em
projects.instances.databases.updateDdl
. Para base de dados, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db
Para o corpo do pedido, use o seguinte:
{ "statements": [ "ALTER TABLE Albums ADD COLUMN MarketingBudget INT64" ] }
A matriz
statements
contém as declarações DDL que definem o esquema.Clique em Executar. Este processo pode demorar alguns minutos, mesmo depois de a chamada REST devolver uma resposta. A resposta devolve uma operação de longa duração que pode consultar para verificar o respetivo estado.
- Clique em
projects.instances.databases.sessions.commit
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "singleUseTransaction": { "readWrite": {} }, "mutations": [ { "update": { "table": "Albums", "columns": [ "SingerId", "AlbumId", "MarketingBudget" ], "values": [ [ "1", "1", "100000" ], [ "2", "2", "500000" ] ] } } ] }
Clique em Executar. A resposta mostra a data/hora da confirmação.
- Clique em
projects.instances.databases.sessions.executeSql
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "sql": "SELECT SingerId, AlbumId, MarketingBudget FROM Albums" }
Clique em Executar. Como parte da resposta, 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 ] ]
- Clique em
projects.instances.databases.updateDdl
. Para base de dados, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db
Para o corpo do pedido, use o seguinte:
{ "statements": [ "CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)" ] }
Clique em Executar. Este processo pode demorar alguns minutos, mesmo depois de a chamada REST devolver uma resposta. A resposta devolve uma operação de longa duração que pode consultar para verificar o respetivo estado.
- Clique em
projects.instances.databases.sessions.executeSql
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "sql": "SELECT AlbumId, AlbumTitle, MarketingBudget FROM Albums WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo'" }
Clique em Executar. Como parte da resposta, deve ver as seguintes linhas:
"rows": [ [ "2", "Go, Go, Go", null ], [ "2", "Forever Hold Your Peace", "500000" ] ]
- Clique em
projects.instances.databases.sessions.read
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "table": "Albums", "columns": [ "AlbumId", "AlbumTitle" ], "keySet": { "all": true }, "index": "AlbumsByAlbumTitle" }
Clique em Executar. Como parte da resposta, deve ver as seguintes linhas:
"rows": [ [ "2", "Forever Hold Your Peace" ], [ "2", "Go, Go, Go" ], [ "1", "Green" ], [ "3", "Terrified" ], [ "1", "Total Junk" ] ]
- Clique em
projects.instances.databases.updateDdl
. Para base de dados, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db
Para o corpo do pedido, use o seguinte:
{ "statements": [ "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)" ] }
Clique em Executar. Este processo pode demorar alguns minutos, mesmo depois de a chamada REST devolver uma resposta. A resposta devolve uma operação de longa duração que pode consultar para verificar o respetivo estado.
- Clique em
projects.instances.databases.sessions.read
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "table": "Albums", "columns": [ "AlbumId", "AlbumTitle", "MarketingBudget" ], "keySet": { "all": true }, "index": "AlbumsByAlbumTitle2" }
Clique em Executar. Como parte da resposta, 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" ] ]
- Clique em
projects.instances.databases.sessions.beginTransaction
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
Para o corpo do pedido, use o seguinte:
{ "options": { "readOnly": {} } }
Clique em Executar.
A resposta mostra o ID da transação que criou.
- Clique em
projects.instances.databases.sessions.executeSql
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "sql": "SELECT SingerId, AlbumId, AlbumTitle FROM Albums", "transaction": { "id": "[TRANSACTION_ID]" } }
Clique em Executar. Deverá 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" ] ]
- Clique em
projects.instances.databases.sessions.read
. Para sessão, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db/sessions/[SESSION]
(Recebe este valor quando cria uma sessão.)
Para o corpo do pedido, use o seguinte:
{ "table": "Albums", "columns": [ "SingerId", "AlbumId", "AlbumTitle" ], "keySet": { "all": true }, "transaction": { "id": "[TRANSACTION_ID]" } }
Clique em Executar. Deverá 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" ] ]
- Clique em
projects.instances.databases.dropDatabase
. Para name, introduza:
projects/[PROJECT_ID]/instances/test-instance/databases/example-db
Clique em Executar.
- Clique em
projects.instances.delete
. Para name, introduza:
projects/[PROJECT_ID]/instances/test-instance
Clique em Executar.
Formas de fazer chamadas REST
Pode fazer chamadas REST do Spanner através de:
Convenções usadas nesta página
Instâncias
Quando usa o Spanner pela primeira vez, tem de criar uma instância, que é uma atribuição de recursos usados pelas bases de dados do Spanner. Quando cria uma instância, escolhe onde os dados são armazenados e a quantidade de capacidade de computação que a instância tem.
Apresente configurações de instâncias
Quando cria uma instância, especifica uma configuração da instância, que define o posicionamento geográfico e a replicação das suas bases de dados nessa instância. Pode escolher uma configuração regional, que armazena dados numa região, ou uma configuração multirregional, que distribui dados por várias regiões. Saiba mais em Instâncias.
Use projects.instanceConfigs.list
para determinar que configurações estão
disponíveis para o seu projeto Google Cloud .
Usa o valor name
para uma das configurações de instância quando cria a instância.
Crie uma instância
Pode listar as suas instâncias através de
projects.instances.list
.
Crie uma base de dados
Crie uma base de dados com o nome example-db
.
Pode listar as suas bases de dados através do comando
projects.instances.databases.list
.
Crie um esquema
Use a linguagem de definição de dados (DDL) do Spanner para criar, alterar ou eliminar tabelas, bem como para criar ou eliminar índices.
O esquema define duas tabelas, Singers
e Albums
, para uma aplicação de música básica. Estas tabelas são usadas ao longo desta página. Consulte o esquema de exemplo, se ainda não o tiver feito.
Pode obter o seu esquema através de
projects.instances.databases.getDdl
.
Crie uma sessão
Antes de poder adicionar, atualizar, eliminar ou consultar dados, tem de criar uma sessão, que representa um canal de comunicação com o serviço de base de dados do Spanner. (Não usa diretamente uma sessão se estiver a usar uma biblioteca de cliente do Spanner, porque a biblioteca de cliente gere as sessões em seu nome.)
As sessões destinam-se a ser de longa duração. O serviço de base de dados do Spanner pode eliminar uma sessão quando esta estiver inativa durante mais de uma hora. As tentativas de usar um resultado de sessão eliminado resultam em NOT_FOUND
. Se encontrar este erro, crie e use uma nova sessão. Pode ver se uma sessão ainda está ativa através de
projects.instances.databases.sessions.get
.
Para informações relacionadas, consulte o artigo Mantenha uma sessão inativa ativa.
O passo seguinte é escrever dados na sua base de dados.
Escrever dados
Escreve dados usando o tipo Mutation
. Um Mutation
é um contentor para operações de mutação. Um Mutation
representa uma sequência de inserções, atualizações, eliminações e outras ações que podem
ser aplicadas atomicamente a diferentes linhas e tabelas numa base de dados
do Spanner.
Este exemplo usou insertOrUpdate
. Outras operações
para Mutations
são insert
, update
, replace
e delete
.
Para obter informações sobre como codificar tipos de dados, consulte TypeCode.
Consultar dados através de SQL
Leia dados através da API de leitura
Atualize o esquema da base de dados
Suponha que precisa de adicionar uma nova coluna denominada MarketingBudget
à tabela Albums
, o que requer uma atualização ao esquema da base de dados. O Spanner
suporta atualizações de esquemas a uma base de dados enquanto a base de dados continua a servir
tráfego. As atualizações do esquema não requerem a colocação da base de dados offline e não bloqueiam tabelas nem colunas inteiras. Pode continuar a escrever dados na base de dados durante a atualização do esquema.
Adicione uma coluna
Escreva dados na nova coluna
O código seguinte escreve dados na nova coluna. Define MarketingBudget
como 100000
para a linha identificada por Albums(1, 1)
e como 500000
para a linha identificada por Albums(2, 2)
.
Também pode executar uma consulta SQL ou uma chamada de leitura para obter os valores que acabou de escrever.
Veja como executar a consulta:
Use um índice secundário
Suponhamos que quer obter todas as linhas de Albums
que têm valores AlbumTitle
num determinado intervalo. Pode ler todos os valores da coluna AlbumTitle
através de uma declaração SQL ou de uma chamada de leitura e, em seguida, rejeitar as linhas que não cumprem os critérios, mas esta análise completa da tabela é dispendiosa, especialmente para tabelas com muitas linhas. Em alternativa, pode acelerar a obtenção de linhas quando
pesquisa por colunas de chaves não primárias criando um
índice secundário na tabela.
A adição de um índice secundário a uma tabela existente requer uma atualização do esquema. Tal como outras atualizações de esquemas, o Spanner suporta a adição de um índice enquanto a base de dados continua a publicar tráfego. O Spanner repreenche automaticamente o índice com os seus dados existentes. Os preenchimentos podem demorar alguns minutos a serem concluídos, mas não precisa de colocar a base de dados offline nem evitar a escrita em determinadas tabelas ou colunas durante este processo. Para mais detalhes, consulte o artigo sobre o preenchimento do índice.
Depois de adicionar um índice secundário, o Spanner usa-o automaticamente para consultas SQL que provavelmente são executadas mais rapidamente com o índice. Se usar a interface read, tem de especificar o índice que quer usar.
Adicione um índice secundário
Pode adicionar um índice através de updateDdl
.
Consultar através do índice
Leia através do índice
Adicione um índice com a cláusula STORING
Pode ter reparado que o exemplo de leitura acima não incluiu a leitura da coluna MarketingBudget
. Isto deve-se ao facto de a interface de leitura do Spanner não suportar a capacidade de juntar um índice a 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.
Pode adicionar um índice STORING através de updateDdl
.
Agora, pode executar uma leitura que obtenha todas as colunas AlbumId
, AlbumTitle
e MarketingBudget
do índice AlbumsByAlbumTitle2
:
Obtenha dados através de transações só de leitura
Suponhamos que quer executar mais do que uma leitura na mesma data/hora. As transações de leitura exclusiva observam um prefixo consistente do histórico de confirmações de transações, pelo que a sua aplicação recebe sempre dados consistentes.
Crie uma transação só de leitura
Agora, pode usar a transação de leitura apenas para obter dados com uma data/hora consistente, mesmo que os dados tenham sido alterados desde que criou a transação de leitura apenas.
Execute uma consulta através da transação só de leitura
Leitura através da transação só de leitura
O Spanner também suporta transações de leitura/escrita, que executam um conjunto de leituras e escritas de forma atómica num único ponto lógico no tempo. Para mais informações, consulte Transações de leitura/escrita. (A funcionalidade Experimentar! não é adequada para demonstrar uma transação de leitura/escrita.)
Limpeza
Para evitar incorrer em custos adicionais na sua conta Google Cloud relativos aos recursos usados neste tutorial, elimine a base de dados e a instância que criou.
Elimine uma base de dados
Elimine uma instância
O que se segue?
- Aceda ao Spanner numa instância de máquina virtual: crie uma instância de máquina virtual com acesso à sua base de dados do Spanner.
- Saiba mais sobre os conceitos do Spanner.