本页面介绍了如何在上下文之外在 Spanner 中执行读取操作。 读写事务如果您属于以下任一情况 您应改为参阅交易页面:
如果需要写入,则根据一个或多个读取的值,应该将读取作为读写事务的一部分执行。有关 请参阅 读写事务。
如果您正在进行多次读取调用,并且它们需要数据的一致视图,则应该将读取作为只读事务的一部分执行。如需了解详情,请参阅 只读事务。
读取类型
Spanner 让您能确定当您使用 Cloud Spanner 时 通过提供两种类型的读取来读取数据:
- “强读”是读取当前时间戳处的数据,并保证能够查看读取开始之前已提交的所有数据。Spanner 默认使用强读来处理读取请求。
- “过时读取”是读取过去时间戳处的数据。如果您的应用对延迟比较敏感,但能容忍过时数据,则过时读取可以带来性能优势。
如需选择所需的读取类型,请设置时间戳边界 读取请求中包含的资源选择时间戳时,请遵循以下最佳实践 绑定:
尽可能选择强读。这些是默认时间戳 受 Spanner 读取(包括只读事务)的约束。强读保证能够观察到在操作开始之前提交的所有事务的影响,这与哪个副本接收读取无关。正因为如此,强读使应用代码更简单,应用更可靠。详细了解 Spanner 的一致性 TrueTime 和外部一致性中的属性。
如果在某些情况下,延迟导致无法执行强读,则使用“过时” 读取(有界限过时或精确过时),以提高 不需要读取的位置尽可能保持最新状态如描述 在复制页面上,15 秒是 合理过时值,以提高性能。
以数据库角色读取数据
如果您是精细访问权限控制用户,则必须选择 可执行 SQL 语句和查询以及执行行的数据库角色 数据库操作您的角色选择在整个会话期间保持不变 直到您更改角色为止。
如需了解如何以数据库角色执行读取操作,请参阅 通过精细的访问权限控制机制访问数据库。
单次读取方法
Spanner 支持单次读取方法(即 事务上下文)在数据库中执行以下操作:
- 将读取作为 SQL 查询语句执行或使用 Spanner 的 read API。
- 对表中的单行或多行执行强读。
- 从表中的单行或多行执行过时读取。
- 从二级索引中的单行或多行读取。
如果要将单个读取操作路由到特定副本或区域 多区域实例配置或自定义区域配置中 具有可选只读区域,请参阅定向读取。
以下各部分介绍了如何使用 Spanner 客户端库。
执行查询
下面演示了如何对数据库执行 SQL 查询语句。
GoogleSQL
C++
使用 ExecuteQuery()
对数据库执行 SQL 查询语句。
C#
使用 ExecuteReaderAsync()
来查询数据库。
Go
使用 Client.Single().Query
来查询数据库。
Java
使用 ReadContext.executeQuery
来查询数据库。
Node.js
使用 Database.run
来查询数据库。
PHP
使用 Database::execute
来查询数据库。
Python
使用 Database.execute_sql
来查询数据库。
Ruby
使用 Client#execute
来查询数据库。
构造 SQL 语句时,请参阅 SQL 查询语法以及函数和运算符参考资料。
执行强读
下面演示了如何对数据库中的零行或多行执行强读。
GoogleSQL
C++
读取数据的代码与上一个查询示例相同 通过执行 SQL 查询访问 Spanner。
C#
读取数据的代码与上一个查询示例相同 通过执行 SQL 查询访问 Spanner。
Go
使用 Client.Single().Read
从数据库中读取行。
该示例使用 AllKeys
来定义要读取的键或键范围的集合。
Java
使用 ReadContext.read
从数据库中读取行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
Node.js
使用 Table.read
从数据库中读取行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
PHP
使用 Database::read
从数据库中读取行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
Python
使用 Database.read
从数据库中读取行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
Ruby
使用 Client#read
从数据库中读取行。
执行过时读取
以下示例代码演示了如何使用精确过时时间戳边界对数据库中的零行或多行执行过时读取。如需了解如何使用有界限过时时间戳边界执行过时读取,请参阅示例代码后面的注释。如需详细了解不同类型的可用时间戳边界,请参阅时间戳边界。
GoogleSQL
C++
将 ExecuteQuery()
与 MakeReadOnlyTransaction()
和 Transaction::ReadOnlyOptions()
配合使用以执行过时读取。
C#
对具有指定 TimestampBound.OfExactStaleness()
值的 connection
使用 BeginReadOnlyTransactionAsync
方法来查询数据库。
Go
使用 Client.ReadOnlyTransaction().WithTimestampBound()
并指定 ExactStaleness
值,以使用精确过时时间戳边界读取数据库中的行。
该示例使用 AllKeys
来定义要读取的键或键范围的集合。
Java
对具有指定 TimestampBound.ofExactStaleness()
的 ReadContext
使用 read
方法,通过精确过时时间戳边界读取数据库中的行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
Node.js
搭配使用 Table.read
和 exactStaleness
选项,利用精确过时时间戳边界读取数据库中的行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
PHP
利用 Database::read
和指定的 exactStaleness
值,通过精确过时时间戳边界读取数据库中的行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
Python
对具有指定 exact_staleness
的 Database
snapshot
使用 read
方法,通过精确过时时间戳边界读取数据库中的行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
Ruby
对具有指定 staleness
值(以秒为单位)的快照 Client
使用 read
方法,通过精确过时时间戳边界从数据库读取行。
使用索引执行读取
下面展示了如何使用 index:
GoogleSQL
C++
使用 Read()
函数通过索引执行读取。
C#
执行一个显式指定索引的查询,通过索引读取数据:
Go
使用 Client.Single().ReadUsingIndex
,以便通过索引从数据库读取行。
Java
使用 ReadContext.readUsingIndex
,以便通过索引从数据库读取行。
Node.js
使用 Table.read
并在查询中指定索引,以便通过索引从数据库读取行。
PHP
使用 Database::read
并指定索引,以便通过索引从数据库读取行。
Python
使用 Database.read
并指定索引,以便通过索引从数据库读取行。
Ruby
使用 Client#read
并指定索引,以便通过索引从数据库读取行。
并行读取数据
执行涉及大量
可以使用 PartitionQuery
更快地获得结果。API 将查询划分为多个批次,或者
分区,方法是使用多台机器并行提取分区。是
请注意,使用 PartitionQuery
API 会导致更长的延迟时间,因为它
只能用于批量操作,例如导出或扫描
数据库。
您可以使用 Spanner 并行执行任何读取 API 操作 客户端库。不过,只有在查询必须满足以下条件时,您才能对 SQL 查询进行分区: 可根分区若要使查询可进行根分区,查询计划必须 满足以下条件之一:
查询执行计划中的第一个运算符是分布式联合运算符 并且查询执行计划仅包含一个分布式联合 (不包括本地分发联盟)。您的查询计划不能包含任何其他 分布式运算符, 分布式交叉应用。
查询计划中没有分布式运算符。
PartitionQuery
API 以批量模式运行查询。Spanner
可能会选择一个让查询可根分区的查询执行计划
在批处理模式下运行时。因此,PartitionQuery
API 和
Spanner Studio 可能使用不同的查询执行计划
。您可能无法获取查询执行计划
由 Spanner Studio 上的 PartitionQuery
API 使用。
对于此类分区查询,您可以选择启用 Spanner Data Boost。 借助 Data Boost,您可以运行大型分析查询 而对预配节点上的现有工作负载几乎没有影响 Spanner 实例。C++、Go、Java、Node.js 和 Python 此页面上的代码示例展示了如何启用 Data Boost。
如需详细了解 Data Boost,请参阅 Data Boost 概览。
GoogleSQL
C++
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 批处理事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
C#
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 批处理事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
Go
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 客户端和事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
Java
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 批处理客户端和事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
Node.js
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 客户端和一个批处理。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
PHP
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 客户端和一个批处理。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
Python
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 客户端和批处理事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
Ruby
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 批处理客户端。
- 为查询创建分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。