目标
本教程将介绍如何使用适用于 PostgreSQL 驱动程序的 Spanner PGAdapter 本地代理完成以下步骤:
- 创建 Spanner 实例和数据库。
- 写入、读取数据库中的数据和对数据执行 SQL 查询。
- 更新数据库架构。
- 使用读写事务更新数据。
- 向数据库添加二级索引。
- 使用索引来读取数据和对数据执行 SQL 查询。
- 使用只读事务检索数据。
费用
本教程使用 Spanner,它是Google Cloud的可计费组件。如需了解 Spanner 的使用费用,请参阅价格。
准备工作
完成设置中介绍的步骤,包括创建和设置默认 Google Cloud 项目、启用结算功能、启用 Cloud Spanner API 以及设置 OAuth 2.0 来获取身份验证凭据以使用 Cloud Spanner API。
尤其要确保运行 gcloud auth
application-default login
,以便使用身份验证凭据设置本地开发环境。
准备本地 PGAdapter 环境
您可以将 PostgreSQL 驱动程序与 PGAdapter 结合使用,以连接到 Spanner。PGAdapter 是一个本地代理,用于将 PostgreSQL 网络协议转换为 Spanner gRPC 协议。
PGAdapter 需要 Java 或 Docker 才能运行。
在开发机器上安装以下任一软件(如果尚未安装):
将示例应用代码库克隆到本地机器:
git clone https://github.com/GoogleCloudPlatform/pgadapter.git
切换到包含 Spanner 示例代码的目录:
psql
cd pgadapter/samples/snippets/psql-snippets
Java
cd pgadapter/samples/snippets/java-snippets mvn package -DskipTests
Go
cd pgadapter/samples/snippets/golang-snippets
Node.js
cd pgadapter/samples/snippets/nodejs-snippets npm install
Python
cd pgadapter/samples/snippets/python-snippets python -m venv ./venv pip install -r requirements.txt cd samples
C#
cd pgadapter/samples/snippets/dotnet-snippets
创建实例
首次使用 Spanner 时,您必须创建一个实例,实例是 Spanner 数据库使用的资源分配单位。创建实例时,请选择一个实例配置(决定数据的存储位置),同时选择要使用的节点数(决定实例中服务资源和存储资源的数量)。
执行以下命令,在区域 us-central1
中创建具有 1 个节点的 Spanner 实例:
gcloud spanner instances create test-instance --config=regional-us-central1 \
--description="Test Instance" --nodes=1
请注意,此命令将创建一个具有以下特征的实例:
- 实例 ID 为
test-instance
- 显示名为
Test Instance
- 实例配置为
regional-us-central1
(单区域配置将数据存储在单个区域中,而多区域配置则将数据分布在多个区域中。如需了解详情,请参阅实例简介。) - 节点数为 1(
node_count
对应于实例中数据库可用的服务资源和存储资源的数量。如需了解详情,请参阅节点和处理单元。)
您应该会看到:
Creating instance...done.
浏览示例文件
示例代码库包含一个示例,展示了如何将 Spanner 与 PGAdapter 搭配使用。
请浏览samples/snippets
文件夹,其中说明了如何使用 Spanner。代码展示了如何创建和使用新数据库。数据使用架构和数据模型页面中显示的示例架构。
启动 PGAdapter
在本地开发机器上启动 PGAdapter,并将其指向您创建的实例。
以下命令假定您已执行 gcloud auth application-default login
。
Java 应用
wget https://storage.googleapis.com/pgadapter-jar-releases/pgadapter.tar.gz \
&& tar -xzvf pgadapter.tar.gz
java -jar pgadapter.jar -i test-instance
Docker
docker pull gcr.io/cloud-spanner-pg-adapter/pgadapter
docker run \
--name pgadapter \
--rm -d -p 5432:5432 \
-v "$HOME/.config/gcloud":/gcloud:ro \
--env CLOUDSDK_CONFIG=/gcloud \
gcr.io/cloud-spanner-pg-adapter/pgadapter \
-i test-instance -x
模拟器
docker pull gcr.io/cloud-spanner-pg-adapter/pgadapter-emulator
docker run \
--name pgadapter-emulator \
--rm -d \
-p 5432:5432 \
-p 9010:9010 \
-p 9020:9020 \
gcr.io/cloud-spanner-pg-adapter/pgadapter-emulator
这会使用嵌入式 Spanner 模拟器启动 PGAdapter。此嵌入式模拟器会自动创建您连接到的任何 Spanner 实例或数据库,而无需您事先手动创建。
我们建议您在生产环境中将 PGAdapter 作为边车容器或进程内依赖项运行。如需详细了解如何在生产环境中部署 PGAdapter,请参阅选择运行 PGAdapter 的方法。
创建数据库
gcloud spanner databases create example-db --instance=test-instance \
--database-dialect=POSTGRESQL
您应该会看到:
Creating database...done.
创建表
以下代码会在数据库中创建两个表。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./create_tables.sh example-db
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar createtables example-db
Go
go run sample_runner.go createtables example-db
Node.js
npm start createtables example-db
Python
python create_tables.py example-db
C#
dotnet run createtables example-db
下一步是将数据写入数据库。
创建连接
您必须先创建与 PGAdapter 的连接,然后才能执行读写操作。您与 Spanner 的所有交互都必须通过Connection
进行。数据库名称在连接字符串中指定。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./create_connection.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar createconnection example-db
Go
go run sample_runner.go createconnection example-db
Node.js
npm start createconnection example-db
Python
python create_connection.py example-db
C#
dotnet run createconnection example-db
使用 DML 写入数据
您可以在读写事务中使用数据操纵语言 (DML) 插入数据。
以下示例展示了如何使用 PostgreSQL 驱动程序在 Spanner 上执行 DML 语句。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./write_data_with_dml.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar writeusingdml example-db
Go
go run sample_runner.go writeusingdml example-db
Node.js
npm start writeusingdml example-db
Python
python write_data_with_dml.py example-db
C#
dotnet run writeusingdml example-db
您应该会看到以下响应:
4 records inserted.
使用 DML 批处理写入数据
PGAdapter 支持执行 DML 批处理。一次性发送多个 DML 语句可减少对 Spanner 的往返次数,并提升应用的性能。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./write_data_with_dml_batch.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar writeusingdmlbatch example-db
Go
go run sample_runner.go writeusingdmlbatch example-db
Node.js
npm start writeusingdmlbatch example-db
Python
python write_data_with_dml_batch.py example-db
C#
dotnet run writeusingdmlbatch example-db
您应该会看到:
3 records inserted.
使用变更写入数据
您还可以使用变更插入数据。
PGAdapter 会将 PostgreSQL COPY
命令转换为更改。使用 COPY
是快速在 Spanner 数据库中插入数据的最有效方法。
COPY
操作默认是原子操作。Spanner 上的原子操作受提交大小限制的约束。如需了解详情,请参阅 CRUD 限制。
以下示例展示了如何执行非原子 COPY
操作。这样,COPY
操作就可以超出提交大小限制。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行该示例:
psql
PGDATABASE=example-db ./write_data_with_copy.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar write example-db
Go
go run sample_runner.go write example-db
Node.js
npm start write example-db
Python
python write_data_with_copy.py example-db
C#
dotnet run write example-db
您应该会看到:
Copied 5 singers
Copied 5 albums
使用 SQL 查询数据
Spanner 支持使用 SQL 接口读取数据,您可以使用 Google Cloud CLI 在命令行中使用该接口,也可以通过 PostgreSQL 驱动程序以编程方式使用该接口。
在命令行中
执行以下 SQL 语句,读取 Albums
表中所有列的值:
gcloud spanner databases execute-sql example-db --instance=test-instance \
--sql='SELECT singer_id, album_id, album_title FROM albums'
结果应为:
SingerId AlbumId AlbumTitle
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
使用 PostgreSQL 驱动程序
除了在命令行上执行 SQL 语句外,还可以使用 PostgreSQL 驱动程序以编程方式发出相同的 SQL 语句。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./query_data.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar query example-db
Go
go run sample_runner.go query example-db
Node.js
npm start query example-db
Python
python query_data.py example-db
C#
dotnet run query example-db
您应该会看到以下结果:
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
使用 SQL 参数进行查询
如果您的应用中有频繁执行的查询,您可以通过对其进行参数化来提高其性能。生成的参数查询可以缓存下来并重复使用,这样做可以降低编译开销。如需了解详情,请参阅使用查询参数来加快频繁执行的查询的运行速度。
以下示例演示了如何在 WHERE
子句中使用参数来查询包含特定 LastName
值的记录。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行该示例:
psql
PGDATABASE=example-db ./query_data_with_parameter.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar querywithparameter example-db
Go
go run sample_runner.go querywithparameter example-db
Node.js
npm start querywithparameter example-db
Python
python query_data_with_parameter.py example-db
C#
dotnet run querywithparameter example-db
您应该会看到以下结果:
12 Melissa Garcia
更新数据库架构
假设您需要将名为 MarketingBudget
的新列添加到 Albums
表。向现有表添加新列需要更新数据库架构。Spanner 支持在数据库继续处理流量的同时,对数据库进行架构更新。架构更新不需要使数据库离线,并且不会锁定整个表或列;在架构更新期间,您可以继续将数据写入数据库。如需详细了解支持的架构更新和架构更改性能,请参阅进行架构更新。
添加列
您可以使用 Google Cloud CLI 在命令行中添加列,也可以使用 PostgreSQL 驱动程序以编程方式添加列。
在命令行中
使用以下 ALTER TABLE
命令向表添加新列:
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='ALTER TABLE albums ADD COLUMN marketing_budget BIGINT'
您应该会看到:
Schema updating...done.
使用 PostgreSQL 驱动程序
使用 PostgreSQL 驱动程序执行 DDL 语句以修改架构:
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./add_column.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar addmarketingbudget example-db
Go
go run sample_runner.go addmarketingbudget example-db
Node.js
npm start addmarketingbudget example-db
Python
python add_column.py example-db
C#
dotnet run addmarketingbudget example-db
您应该会看到:
Added marketing_budget column
执行 DDL 批处理
建议一次性批量执行多项架构修改。您可以通过以下方式在一个批处理中执行多条 DDL 语句:使用 PostgreSQL 驱动程序的内置批处理功能;将所有 DDL 语句作为一个以分号分隔的 SQL 字符串提交;或使用 START BATCH DDL
和 RUN BATCH
语句。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行该示例:
psql
PGDATABASE=example-db ./ddl_batch.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar ddlbatch example-db
Go
go run sample_runner.go ddlbatch example-db
Node.js
npm start ddlbatch example-db
Python
python ddl_batch.py example-db
C#
dotnet run ddlbatch example-db
您应该会看到:
Added venues and concerts tables
将数据写入新列
以下代码可将数据写入新列。对于 Albums(1, 1)
键控的行,该代码会将 MarketingBudget
设置为 100000
;而对于 Albums(2, 2)
键控的行,该代码会将其设置为 500000
。
COPY
命令转换为更改。默认情况下,COPY
命令会转换为 Insert
更改。执行 set spanner.copy_upsert=true
以将 COPY
命令转换为 InsertOrUpdate
更改。这可用于更新 Spanner 中的现有数据。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./update_data_with_copy.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar update example-db
Go
go run sample_runner.go update example-db
Node.js
npm start update example-db
Python
python update_data_with_copy.py example-db
C#
dotnet run update example-db
您应该会看到:
Updated 2 albums
您也可以执行 SQL 查询来获取刚刚写入的值。
以下是执行查询的代码:
psql
Java
Go
Node.js
Python
C#
使用以下命令运行查询:
psql
PGDATABASE=example-db ./query_data_with_new_column.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar querymarketingbudget example-db
Go
go run sample_runner.go querymarketingbudget example-db
Node.js
npm start querymarketingbudget example-db
Python
python query_data_with_new_column.py example-db
C#
dotnet run querymarketingbudget example-db
您应该会看到:
1 1 100000
1 2 null
2 1 null
2 2 500000
2 3 null
更新数据
您可以在读写事务中使用 DML 来更新数据。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./update_data_with_transaction.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar writewithtransactionusingdml example-db
Go
go run sample_runner.go writewithtransactionusingdml example-db
Node.js
npm start writewithtransactionusingdml example-db
Python
python update_data_with_transaction.py example-db
C#
dotnet run writewithtransactionusingdml example-db
您应该会看到:
Transferred marketing budget from Album 2 to Album 1
事务代码和请求代码
您可以使用事务代码和请求代码来排查 Spanner 中事务和查询的问题。您可以使用 SPANNER.TRANSACTION_TAG
和 SPANNER.STATEMENT_TAG
会话变量设置事务代码和请求代码。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./tags.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar tags example-db
Go
go run sample_runner.go tags example-db
Node.js
npm start tags example-db
Python
python tags.py example-db
C#
dotnet run tags example-db
使用只读事务检索数据
假设您要在同一时间戳执行多个读取操作。只读事务会遵从一致的事务提交历史记录前缀,因此您的应用始终可获得一致的数据。
将连接设置为只读,或使用 SET TRANSACTION READ ONLY
SQL 语句执行只读事务。
下面演示了如何运行查询并在同一只读事务中执行读取操作:
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./read_only_transaction.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar readonlytransaction example-db
Go
go run sample_runner.go readonlytransaction example-db
Node.js
npm start readonlytransaction example-db
Python
python read_only_transaction.py example-db
C#
dotnet run readonlytransaction example-db
您看到的输出结果应该类似于以下内容:
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
2 2 Forever Hold Your Peace
1 2 Go, Go, Go
2 1 Green
2 3 Terrified
1 1 Total Junk
分区查询和 Data Boost
partitionQuery
API 会将查询划分为较小部分(即分区),然后使用多台机器并行提取分区。每个分区都由分区令牌标识。PartitionQuery API 的延迟时间比标准查询 API 更长,因为它仅适用于导出或扫描整个数据库等批量操作。
Data Boost 使您可以执行分析查询和数据导出,且对预配的 Spanner 实例上的现有工作负载几乎没有影响。Data Boost 仅支持分区查询。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./data_boost.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar databoost example-db
Go
go run sample_runner.go databoost example-db
Node.js
npm start databoost example-db
Python
python data_boost.py example-db
C#
dotnet run databoost example-db
如需详细了解如何运行分区查询以及如何将 Data Boost 与 PGAdapter 搭配使用,请参阅:Data Boost 和分区查询语句
分区 DML
分区数据操纵语言 (DML) 专为以下类型的批量更新和删除而设计:
- 定期清理和垃圾回收。
- 使用默认值回填新列。
psql
Java
Go
Node.js
Python
C#
使用以下命令运行示例:
psql
PGDATABASE=example-db ./partitioned_dml.sh
Java
java -jar target/pgadapter-snippets/pgadapter-samples.jar partitioneddml example-db
Go
go run sample_runner.go partitioneddml example-db
Node.js
npm start partitioneddml example-db
Python
python partitioned_dml.py example-db
C#
dotnet run datpartitioneddmlboost example-db
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生额外费用,请删除数据库和您创建的实例。
删除数据库
如果您删除一个实例,则该实例中的所有数据库都会自动删除。 本步骤演示了如何在不删除实例的情况下删除数据库(您仍需为该实例付费)。
在命令行中
gcloud spanner databases delete example-db --instance=test-instance
使用 Google Cloud 控制台
前往 Google Cloud 控制台中的 Spanner 实例页面。
点击实例。
点击您想删除的数据库。
在数据库详细信息页面中,点击删除。
确认您要删除数据库并点击删除。
删除实例
删除实例会自动删除在该实例中创建的所有数据库。
在命令行中
gcloud spanner instances delete test-instance
使用 Google Cloud 控制台
前往 Google Cloud 控制台中的 Spanner 实例页面。
点击您的实例。
点击删除。
确认您要删除实例并点击删除。
后续步骤
了解如何使用虚拟机实例访问 Spanner。
如需了解授权和身份验证凭据,请参阅使用客户端库向 Cloud 服务进行身份验证。
详细了解 Spanner 架构设计最佳实践。