本页面介绍了如何在上下文之外在 Spanner 中执行读取操作。 读写事务如果您属于以下任一情况 您应改为参阅事务页面:
如果需要写入,则根据一个或多个读取的值,应该将读取作为读写事务的一部分执行。如需了解详情,请参阅读写事务。
如果您正在进行多次读取调用,并且它们需要数据的一致视图,则应该将读取作为只读事务的一部分执行。如需了解详情,请参阅只读事务。
读取类型
Spanner 提供两种类型的读取,让您能在读取数据时确定数据的新鲜程度:
- “强读”是读取当前时间戳处的数据,并保证能够查看读取开始之前已提交的所有数据。Spanner 默认使用强读来处理读取请求。
- “过时读取”是读取过去时间戳处的数据。如果您的应用对延迟比较敏感,但能容忍过时数据,则过时读取可以带来性能优势。
如需选择所需的读取类型,请在读取请求上设置时间戳边界。选择时间戳边界时,请遵循以下最佳实践:
尽可能选择强读。这些是 Spanner 读取(包括只读事务)的默认时间戳边界。强读保证能够观察到在操作开始之前提交的所有事务的影响,这与哪个副本接收读取无关。正因为如此,强读使应用代码更简单,应用更可靠。如需详细了解 Spanner 的一致性特性,请参阅 TrueTime 和外部一致性。
如果在某些情况下,延迟导致无法执行强读,则可以使用过时读取(有界限过时或精确过时)来提高不要求读取尽可能新鲜的场合的性能。如复制页面中所述,15 秒是一个合理的过时值,有助于提高性能。
使用数据库角色读取数据
如果您是精细访问权限控制用户,则必须选择数据库角色才能执行 SQL 语句和查询,以及对数据库执行行操作。您选择的角色会在整个会话期间保持不变,除非您更改角色。
如需了解如何使用数据库角色执行读取操作,请参阅使用精细访问权限控制访问数据库。
单次读取方法
Spanner 支持对数据库使用单次读取方法(即在事务上下文之外进行读取),可实现以下目的:
- 以 SQL 查询语句形式或使用 Spanner 的读取 API 执行读取。
- 对表中的单行或多行执行强读。
- 从表中的单行或多行执行过时读取。
- 从二级索引中的单行或多行读取。
如果您想将单次读取路由到多区域实例配置或包含可选只读区域的自定义区域配置中的特定副本或区域,请参阅定向读取。
以下部分介绍了如何使用 Spanner 客户端库使用读取方法。
执行查询
下面演示了如何对数据库执行 SQL 查询语句。
使用 ExecuteQuery()
对数据库执行 SQL 查询语句。
使用 ExecuteReaderAsync()
来查询数据库。
使用 Client.Single().Query
来查询数据库。
使用 ReadContext.executeQuery
来查询数据库。
使用 Database.run
来查询数据库。
使用 Database::execute
来查询数据库。
使用 Database.execute_sql
来查询数据库。
使用 Client#execute
来查询数据库。
构造 SQL 语句时,请参阅 SQL 查询语法以及函数和运算符参考资料。
执行强读
下面演示了如何对数据库中的零行或多行执行强读。
读取数据的代码与前一个通过执行 SQL 查询来查询 Spanner 的示例相同。
读取数据的代码与前一个通过执行 SQL 查询来查询 Spanner 的示例相同。
使用 Client.Single().Read
从数据库中读取行。
该示例使用 AllKeys
来定义要读取的键或键范围的集合。
使用 ReadContext.read
从数据库中读取行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
使用 Table.read
从数据库中读取行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
使用 Database::read
从数据库中读取行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
使用 Database.read
从数据库中读取行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
使用 Client#read
从数据库中读取行。
执行过时读取
以下示例代码演示了如何使用精确过时时间戳边界对数据库中的零行或多行执行过时读取。如需了解如何使用有界限过时时间戳边界执行过时读取,请参阅示例代码后面的注释。如需详细了解不同类型的可用时间戳边界,请参阅时间戳边界。
将 ExecuteQuery()
与 MakeReadOnlyTransaction()
和 Transaction::ReadOnlyOptions()
配合使用以执行过时读取。
对具有指定 TimestampBound.OfExactStaleness()
值的 connection
使用 BeginReadOnlyTransactionAsync
方法来查询数据库。
使用 Client.ReadOnlyTransaction().WithTimestampBound()
并指定 ExactStaleness
值,以使用精确过时时间戳边界读取数据库中的行。
该示例使用 AllKeys
来定义要读取的键或键范围的集合。
对具有指定 TimestampBound.ofExactStaleness()
的 ReadContext
使用 read
方法,通过精确过时时间戳边界读取数据库中的行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
搭配使用 Table.read
和 exactStaleness
选项,利用精确过时时间戳边界读取数据库中的行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
利用 Database::read
和指定的 exactStaleness
值,通过精确过时时间戳边界读取数据库中的行。
该示例使用 keySet
来定义要读取的键或键范围的集合。
对具有指定 exact_staleness
的 Database
snapshot
使用 read
方法,通过精确过时时间戳边界读取数据库中的行。
该示例使用 KeySet
来定义要读取的键或键范围的集合。
对具有指定 staleness
值(以秒为单位)的快照 Client
使用 read
方法,通过精确过时时间戳边界从数据库读取行。
使用索引执行读取
下面演示了如何使用索引从数据库读取零行或多行:
使用 Read()
函数通过索引执行读取。
执行一个显式指定索引的查询,通过索引读取数据:
使用 Client.Single().ReadUsingIndex
,以便通过索引从数据库读取行。
使用 ReadContext.readUsingIndex
,以便通过索引从数据库读取行。
使用 Table.read
并在查询中指定索引,以便通过索引从数据库读取行。
使用 Database::read
并指定索引,以便通过索引从数据库读取行。
使用 Database.read
并指定索引,以便通过索引从数据库读取行。
使用 Client#read
并指定索引,以便通过索引从数据库读取行。
并行读取数据
执行涉及 Spanner 中大量数据的批量读取或查询操作时,您可以使用 PartitionQuery
API 加快结果的返回速度。该 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 概览。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 批处理事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建 Spanner 批处理事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 客户端和一个事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 批处理客户端和一个事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 客户端和一个批处理。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 客户端和一个批处理。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 客户端和一个批处理事务。
- 为查询生成分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。
此示例提取 Singers
表的 SQL 查询分区,并按照以下步骤对每个分区执行查询:
- 创建一个 Spanner 批处理客户端。
- 为查询创建分区,以便可以将分区分发给多个工作器。
- 检索每个分区的查询结果。