目标
本教程将介绍如何使用 Spanner 完成以下步骤: 适用于 Java 的客户端库:
- 创建 Spanner 实例和数据库。
- 写入、读取数据库中的数据和对数据执行 SQL 查询。
- 更新数据库架构。
- 使用读写事务更新数据。
- 向数据库添加二级索引。
- 使用索引来读取数据和对数据执行 SQL 查询。
- 使用只读事务检索数据。
费用
本教程使用 Spanner,它是 Google Cloud 的收费组件。如需了解 Spanner 的使用费用,请参阅价格。
准备工作
完成设置中介绍的步骤,包括创建和设置默认 Google Cloud 项目、启用结算功能、启用 Cloud Spanner API 以及设置 OAuth 2.0 来获取身份验证凭据以使用 Cloud Spanner API。
尤其要确保运行 gcloud auth
application-default login
,以便使用身份验证凭据设置本地开发环境。
准备本地 Java 环境
在开发机器上安装以下内容(如果尚未安装):
将示例应用代码库克隆到本地机器:
git clone https://github.com/googleapis/java-spanner.git
切换到包含 Spanner 示例代码的目录:
cd java-spanner/samples/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.
浏览示例文件
示例代码库包含一个示例,展示了如何在 Java 中使用 Spanner。
创建数据库
通过在命令行运行以下命令,在名为 test-instance
的实例中创建名为 example-db
的数据库。
GoogleSQL
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
createdatabase test-instance example-db
PostgreSQL
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
createpgdatabase test-instance example-db
您应该会看到:
Created database [example-db]
GoogleSQL
PostgreSQL
下一步是将数据写入数据库。
创建数据库客户端
您必须先创建一个DatabaseClient
,然后才能执行读写操作。您可以将 DatabaseClient
视为数据库连接:
与 Spanner 的交互必须通过 DatabaseClient
进行。通常,您可以在应用启动时创建 DatabaseClient
,然后重复使用该 DatabaseClient
来读取、写入和执行事务。
GoogleSQL
PostgreSQL
每个客户端均使用 Spanner 中的资源,因此最好通过调用 close()
来关闭不需要的客户端。
如需了解详情,请访问DatabaseClient
Javadoc 参考。
使用 DML 写入数据
您可以在读写事务中使用数据操纵语言 (DML) 插入数据。
使用 executeUpdate()
方法来执行 DML 语句。
使用 writeusingdml
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
writeusingdml test-instance example-db
您应该会看到:
4 records inserted.
使用变更写入数据
您还可以使用变更插入数据。
您可以使用 Mutation
对象写入数据。Mutation
对象是用于变更操作的容器。Mutation
表示 Spanner 插入、更新和删除的序列,
以原子方式应用于 Spanner 数据库中的不同行和表。
newInsertBuilder()
Mutation
类中的方法构造了一个 INSERT
变更,该变更会在
在表中添加新行。如果该行已经存在,则写入失败。或者,您可以使用 newInsertOrUpdateBuilder
方法构建 INSERT_OR_UPDATE
变更,该变更会在该行已经存在时更新列值。
DatabaseClient
类中的 write()
方法可写入变更。单个批处理中的所有变更均以原子方式应用。
此代码演示了如何使用变更写入数据:
使用 write
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
write test-instance example-db
您应该会看到命令成功运行。
使用 SQL 查询数据
Spanner 支持使用 SQL 接口读取数据,您可以使用 Google Cloud CLI 在命令行中使用该接口,也可以通过 Java 版 Spanner 客户端库以编程方式使用该接口。
在命令行中
执行以下 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
使用 Java 版 Spanner 客户端库
除了在命令行中执行 SQL 语句外,还可以使用 Java 版 Spanner 客户端库以编程方式发出相同的 SQL 语句。
使用以下方法和类运行 SQL 查询:singleUse()
DatabaseClient
类中的方法:使用此方法读取一个或多个 来自 Spanner 表中的一行或多行的列。退货费用singleUse()
一个ReadContext
对象,用于运行读取或 SQL 语句。ReadContext
类的executeQuery()
方法:使用此方法对数据库执行查询。Statement
类:使用此类构造 SQL 字符串。ResultSet
类:使用此类访问由 SQL 语句或读取调用返回的数据。
下面演示了如何发出查询并访问数据:
使用 query
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
query test-instance 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
值的查询记录。
GoogleSQL
PostgreSQL
使用 queryWithParameter 参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
querywithparameter test-instance example-db
您应该会看到以下结果:
12 Melissa Garcia
使用读取 API 读取数据
除 Spanner 的 SQL 接口外,Spanner 还支持读取接口。
使用ReadContext
类的 read()
方法可从数据库中读取行。使用 KeySet
对象定义要读取的键和键范围的集合。
下面演示了如何读取数据:
使用 read
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
read test-instance example-db
您看到的输出结果应该类似于以下内容:
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
更新数据库架构
假设您需要将名为 MarketingBudget
的新列添加到 Albums
表。向现有表添加新列需要更新数据库架构。Spanner 支持对数据库进行架构更新,同时
以便继续处理流量架构更新不需要
数据库离线,且不会锁定整个表或列;您可以继续
在架构更新期间将数据写入数据库。如需详细了解支持的架构更新和架构更改性能,请参阅进行架构更新。
添加列
您可以使用 Google Cloud CLI 或 以编程方式使用 适用于 Java 的 Spanner 客户端库。
在命令行中
使用以下 ALTER TABLE
命令向表添加新列:
GoogleSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget INT64'
PostgreSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT'
您应该会看到:
Schema updating...done.
使用 Java 版 Spanner 客户端库
使用DatabaseAdminClient
类的 updateDatabaseDdl()
方法来修改架构:
GoogleSQL
PostgreSQL
使用 addmarketingbudget
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
addmarketingbudget test-instance example-db
您应该会看到:
Added MarketingBudget column.
将数据写入新列
以下代码可将数据写入新列。对于 Albums(1, 1)
键控的行,该代码会将 MarketingBudget
设置为 100000
;而对于 Albums(2, 2)
键控的行,该代码会将其设置为 500000
。
使用 update
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
update test-instance example-db
您还可以执行 SQL 查询或读取调用来获取刚才写入的值。
以下是执行查询的代码:
GoogleSQL
PostgreSQL
如需执行此查询,请使用 querymarketingbudget
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
querymarketingbudget test-instance example-db
您应该会看到:
1 1 100000
1 2 NULL
2 1 NULL
2 2 500000
2 3 NULL
更新数据
您可以在读写事务中使用 DML 来更新数据。
您可以使用 executeUpdate()
方法来执行 DML 语句。
GoogleSQL
PostgreSQL
使用 writewithtransactionusingdml
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
writewithtransactionusingdml test-instance example-db
使用二级索引
假设您想要提取 Albums
表中 AlbumTitle
值在特定范围内的所有行。您可以使用 SQL 语句或读取调用读取 AlbumTitle
列中的所有值,然后舍弃不符合条件的行。不过,执行全表扫描费用高昂,特别是对内含大量行的表来说更是如此。相反,如果对表创建二级索引,按非主键列进行搜索,则可以提高行检索速度。
向现有表添加二级索引需要更新架构。点赞 Spanner 支持添加索引,同时 以便继续处理流量Spanner 会自动回填 使用现有数据创建索引。回填可能需要几分钟时间才能完成,但在此过程中,您无需使数据库离线,也无需避免写入已编入索引的表。有关详情,请参阅 添加二级索引。
添加二级索引后,Spanner 会自动将其用于 使用索引可能会提高运行速度的 SQL 查询。如果使用读取接口,则必须指定要使用的索引。
添加二级索引
您可以使用 gcloud CLI 或 以编程方式使用 Java 版 Spanner 客户端库。
在命令行中
使用以下 CREATE INDEX
命令向数据库添加索引:
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)'
您应该会看到:
Schema updating...done.
使用 Java 版 Spanner 客户端库
使用updateDatabaseDdl()
方法以添加索引:DatabaseAdminClient
使用 addindex
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
addindex test-instance example-db
添加索引可能需要几分钟时间。添加索引后,您应该会看到:
Added the AlbumsByAlbumTitle index.
使用索引进行读取
对于 SQL 查询,Spanner 会自动使用适当的索引。在读取接口中,您必须在请求中指定索引。
如需在读取接口中使用索引,请使用 ReadContext
类的 readUsingIndex()
方法。
以下代码会从 AlbumsByAlbumTitle
索引中提取所有 AlbumId
和 AlbumTitle
列。
使用 readindex
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
readindex test-instance example-db
您应该会看到:
2 Forever Hold Your Peace
2 Go, Go, Go
1 Green
3 Terrified
1 Total Junk
添加了仅索引读取的索引
您可能已经注意到,之前的读取示例不包括
MarketingBudget
列。这是因为,Spanner 的读取接口不支持将索引与数据表联接起来查找未存储在索引中的值。
请创建 AlbumsByAlbumTitle
的备用定义,用于将 MarketingBudget
的副本存储到索引中。
在命令行中
GoogleSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)
PostgreSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) INCLUDE (MarketingBudget)
添加索引可能需要几分钟时间。添加索引后,您应该会看到:
Schema updating...done.
使用 Java 版 Spanner 客户端库
使用 DatabaseAdminClient
类的 updateDatabaseDdl()
方法来添加带 STORING
子句的索引(适用于 GoogleSQL)和带 INCLUDE
子句的索引(适用于 PostgreSQL):
GoogleSQL
PostgreSQL
使用 addstoringindex
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
addstoringindex test-instance example-db
添加索引可能需要几分钟时间。添加索引后,应显示如下信息:
Added AlbumsByAlbumTitle2 index
现在,当您执行读取操作时便可从 AlbumsByAlbumTitle2
索引中提取所有 AlbumId
、AlbumTitle
和 MarketingBudget
列:
使用 readstoringindex
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
readstoringindex test-instance example-db
您看到的输出结果应该类似于以下内容:
2 Forever Hold Your Peace 300000
2 Go, Go, Go NULL
1 Green NULL
3 Terrified NULL
1 Total Junk 300000
使用只读事务检索数据
假设您要在同一时间戳执行多个读取操作。只读事务会观察事务提交记录的一致前缀,以便应用始终获得一致的数据。
使用 ReadOnlyTransaction
对象执行只读事务。使用 DatabaseClient
类的 readOnlyTransaction()
方法来获取 ReadOnlyTransaction
对象。
下面演示了如何运行查询并在同一只读事务中执行读取操作:
使用 readonlytransaction
参数运行示例。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
readonlytransaction test-instance example-db
您看到的输出结果应该类似于以下内容:
2 2 Forever Hold Your Peace
1 2 Go, Go, Go
2 1 Green
2 3 Terrified
1 1 Total Junk
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
清理
为避免因本教程中使用的资源导致您的 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 架构设计最佳实践。