目标
本教程将介绍如何使用 Spanner 数据库/SQL 驱动程序完成以下步骤:
- 创建 Spanner 实例和数据库。
- 写入、读取数据库中的数据和对数据执行 SQL 查询。
- 更新数据库架构。
- 使用读写事务更新数据。
- 向数据库添加二级索引。
- 使用索引来读取数据和对数据执行 SQL 查询。
- 使用只读事务检索数据。
费用
本教程使用 Spanner,它是Google Cloud的可计费组件。如需了解 Spanner 的使用费用,请参阅价格。
准备工作
完成设置中介绍的步骤,包括创建和设置默认 Google Cloud 项目、启用结算功能、启用 Cloud Spanner API 以及设置 OAuth 2.0 来获取身份验证凭据以使用 Cloud Spanner API。
尤其要确保运行 gcloud auth
application-default login
,以便使用身份验证凭据设置本地开发环境。
准备本地数据库/SQL 环境
如果开发机器上尚未安装 Go,请先进行安装。
将示例代码库克隆到您的本地机器:
git clone https://github.com/googleapis/go-sql-spanner.git
切换到包含 Spanner 示例代码的目录:
cd go-sql-spanner/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 与数据库/SQL 搭配使用。
请浏览getting_started_guide.go
文件,其中说明了如何使用 Spanner。代码展示了如何创建和使用新数据库。数据使用架构和数据模型页面中显示的示例架构。
创建数据库
gcloud spanner databases create example-db --instance=test-instance
您应该会看到:
Creating database...done.
创建表
以下代码会在数据库中创建两个表。
使用以下命令运行示例:
go run getting_started_guide.go createtables projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
下一步是将数据写入数据库。
创建连接
您必须先创建一个sql.DB
,然后才能执行读写操作。sql.DB
包含一个连接池,可用于与 Spanner 交互。数据库名称和其他连接属性在 database/sql 数据源名称中指定。
使用 DML 写入数据
您可以在读写事务中使用数据操纵语言 (DML) 插入数据。
使用 ExecContext
函数来执行 DML 语句。
使用以下命令运行示例:
go run getting_started_guide.go dmlwrite projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
结果显示:
4 records inserted.
使用变更写入数据
您还可以使用变更插入数据。
Mutation
是用于变更操作的容器。Mutation
代表插入、更新和删除等一系列操作,Spanner 将这些操作以原子方式应用于 Spanner 数据库中的不同行和表。
使用 Mutation.InsertOrUpdate()
构建 INSERT_OR_UPDATE
变更,该变更会添加新行或更新列值(如果该行已经存在)。或者,使用 Mutation.Insert()
方法构建 INSERT
变更,该变更会添加新行。
conn.Raw
函数获取对底层 Spanner 连接的引用。SpannerConn.Apply
函数以原子方式将变更应用于数据库。
以下代码展示了如何使用变更写入数据:
使用 write
参数运行以下示例:
go run getting_started_guide.go write projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
使用 SQL 查询数据
Spanner 支持使用 SQL 接口读取数据,您可以使用 Google Cloud CLI 在命令行中使用该接口,也可以通过 Spanner 数据库/SQL 驱动程序以编程方式使用该接口。
在命令行中
执行以下 SQL 语句,读取 Albums
表中所有列的值:
gcloud spanner databases execute-sql example-db --instance=test-instance \
--sql='SELECT SingerId, AlbumId, AlbumTitle 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
使用 Spanner 数据库/SQL 驱动程序
除了在命令行上执行 SQL 语句外,还可以使用 Spanner database/sql 驱动程序以编程方式发出相同的 SQL 语句。
以下函数和结构体用于执行 SQL 查询:DB
结构体中的QueryContext
函数:使用此函数可执行返回行的 SQL 语句,例如包含THEN RETURN
子句的查询或 DML 语句。Rows
结构体:使用此结构体访问由 SQL 语句返回的数据。
以下示例使用了 QueryContext
函数:
使用以下命令运行该示例:
go run getting_started_guide.go query projects/$GCLOUD_PROJECT/instances/test-instance/databases/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
值的记录。
Spanner 数据库/SQL 驱动程序同时支持位置查询参数和命名查询参数。SQL 语句中的 ?
表示位置查询参数。将查询参数值作为额外参数传递给 QueryContext
函数。例如:
使用以下命令运行该示例:
go run getting_started_guide.go querywithparameter projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
结果显示:
12 Melissa Garcia
更新数据库架构
假设您需要将名为 MarketingBudget
的新列添加到 Albums
表。向现有表添加新列需要更新数据库架构。Spanner 支持在数据库继续处理流量的同时,对数据库进行架构更新。架构更新不需要使数据库离线,并且不会锁定整个表或列;在架构更新期间,您可以继续将数据写入数据库。如需详细了解支持的架构更新和架构更改性能,请参阅进行架构更新。
添加列
您可以使用 Google Cloud CLI 在命令行中添加列,也可以使用 Spanner 数据库/SQL 驱动程序以编程方式添加列。
在命令行中
使用以下 ALTER TABLE
命令向表添加新列:
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget INT64'
您应该会看到:
Schema updating...done.
使用 Spanner 数据库/SQL 驱动程序
使用ExecContext
函数修改架构:
使用以下命令运行该示例:
go run getting_started_guide.go addcolumn projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
结果显示:
Added MarketingBudget column.
执行 DDL 批处理
我们建议您一次性批量执行多个架构修改。使用 START BATCH DDL
和 RUN BATCH
命令执行 DDL 批处理。以下示例会在一批中创建两个表:
使用以下命令运行该示例:
go run getting_started_guide.go ddlbatch projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
结果显示:
Added Venues and Concerts tables.
将数据写入新列
以下代码可将数据写入新列。对于 Albums(1, 1)
键控的行,该代码会将 MarketingBudget
设置为 100000
;而对于 Albums(2, 2)
键控的行,该代码会将其设置为 500000
。
使用以下命令运行该示例:
go run getting_started_guide.go update projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
结果显示:
Updated 2 albums
您也可以执行 SQL 查询来获取刚刚写入的值。
以下示例使用 QueryContext
函数执行查询:
如需执行此查询,请运行以下命令:
go run getting_started_guide.go querymarketingbudget projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
您应该会看到:
1 1 100000
1 2 null
2 1 null
2 2 500000
2 3 null
更新数据
您可以在读写事务中使用 DML 来更新数据。
调用 DB.BeginTx
以在 database/sql 中执行读写事务。
使用以下命令运行该示例:
go run getting_started_guide.go writewithtransactionusingdml projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
事务代码和请求代码
您可以使用事务代码和请求代码来排查 Spanner 中事务和查询的问题。您可以向 spannerdriver.BeginReadWriteTransaction
函数传递其他事务选项。
使用 spannerdriver.ExecOptions
为 SQL 语句传递其他查询选项。例如:
使用以下命令运行该示例:
go run getting_started_guide.go tags projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
使用只读事务检索数据
假设您要在同一时间戳执行多个读取操作。只读事务会遵从一致的事务提交历史记录前缀,因此您的应用始终可获得一致的数据。
将 TxOptions.ReadOnly
字段设置为 true
以执行只读事务。
下面演示了如何运行查询并在同一只读事务中执行读取操作:
使用以下命令运行该示例:
go run getting_started_guide.go readonlytransaction projects/$GCLOUD_PROJECT/instances/test-instance/databases/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 仅支持分区查询。
以下示例展示了如何使用数据库/SQL 驱动程序通过 Data Boost 执行分区查询:
使用以下命令运行该示例:
go run getting_started_guide.go databoost projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
分区 DML
分区数据操纵语言 (DML) 专为以下类型的批量更新和删除而设计:
- 定期清理和垃圾回收。
- 使用默认值回填新列。
使用以下命令运行该示例:
go run getting_started_guide.go pdml projects/$GCLOUD_PROJECT/instances/test-instance/databases/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 架构设计最佳实践。