读取

本页介绍您可以向 Bigtable 发送的读取请求类型,探讨性能影响,并针对特定类型的查询提供了一些建议。在阅读本页内容之前,您应先熟悉 Bigtable 概览

概览

对 Bigtable 的读取请求按键顺序流式返回所请求行的内容,这意味着它们按存储顺序返回。您可以读取已返回响应的任何写入。

您的表格支持的查询应有助于确定最适合您的用例的读取类型。Bigtable 读取请求分为两大类:

  • 读取一行
  • 扫描或读取多行

读取在行级层属于原子操作。这意味着当您针对某一行发送读取请求时,Bigtable 要么返回整行,要么请求失败,不返回任何行。除非您明确请求,否则不会返回部分行。

我们强烈建议您使用我们的 Cloud Bigtable 客户端库从表中读取数据,而不是直接调用 API。代码示例显示如何发送读取请求,支持多种语言。所有读取请求都进行 ReadRows API 调用。

使用 Data Boost 无服务器计算读取数据

借助 Bigtable Data Boost,您可以运行批量读取作业和查询,而不会影响每日应用流量。Data Boost 是一项无服务器计算服务,可供您读取 Bigtable 数据,同时核心应用使用集群的节点进行计算。

Data Boost 非常适合扫描,不建议用于单行读取。您无法将 Data Boost 用于反向扫描。如需了解详情和资格条件,请参阅 Data Boost 概览

单行读取

您可以根据行键请求一行。单行读取(也称为点读取)与 Data Boost 不兼容。代码示例适用于以下变体:

扫描

扫描是读取 Bigtable 数据最常见的方式。您可以通过指定行键前缀或指定起始和结束行键,从 Bigtable 读取一个范围内的连续行或多个范围内的行。代码示例适用于以下变体:

反向扫描

借助反向扫描,您可以通过指定行键前缀或一系列行来反向读取一系列行。行键前缀用作扫描的起始点,以向后读取。如果您指定行范围,则结束行键将用作扫描的起始点。

按反向顺序扫描对于以下情况非常有用:

  • 您想要查找某个事件(行),然后读取前 N 个事件。
  • 您想要在给定值之前查找最高值。这在使用时间戳作为行键后缀来存储时序数据时会很有帮助。

反向扫描的效率低于正向扫描。通常,对行键进行设计,使大多数扫描为正向。请对较短扫描(例如 50 行或更少)使用反向扫描,以保持低延迟响应时间。

如需向后扫描,请将 ReadRowsRequest 字段 reversed 的值设置为 true。默认值为 false。

使用以下客户端库时,可以进行反向扫描:

  • C++ 版 Bigtable 客户端库 2.18.0 或更高版本
  • Go 版 Bigtable 客户端库 1.21.0 或更高版本
  • Java 版 Bigtable 客户端库 2.24.1 或更高版本
  • Java 版 Bigtable HBase 客户端 2.10.0 或更高版本

如需查看演示如何使用反向扫描的代码示例,请参阅反向扫描

使用场景示例

以下示例展示了如何使用反向扫描来查找客户上次更改密码的时间,以及特定日期附近商品的价格波动情况。

密码重置

假设每一行键均包含客户 ID 和日期(格式为 123ABC#2022-05-02),并且其中一列为 password_reset,该列存储了密码重置时的时间。Bigtable 会按字典顺序自动存储数据,类似于如下所示。请注意,对于未重置密码的行(天),该列不存在。

`123ABC#2022-02-12,password_reset:03`
`123ABC#2022-04-02,password_reset:11`
`123ABC#2022-04-14`
`123ABC#2022-05-02`
`223ABC#2022-05-22`

如果您想要查找客户 123ABC 上次重置密码的时间,则可以针对包含列 password_reset 且行限制为 1 的所有行反向扫描范围 123ABC#123ABC#<DATE>(使用今天的日期或未来的日期)。

价格变动

在此示例中,行键包含产品、型号和时间戳的值,并且其中一列包含产品和型号在给定时间的价格。

`productA#model2#1675604471,price:82.63`
`productA#model2#1676219411,price:82.97`
`productA#model2#1677681011,price:83.15`
`productA#model2#1680786011,price:83.99`
`productA#model2#1682452238,price:83.12`

如果您想要查找 2023 年 2 月 14 日的价格波动情况,则即使表中不存在该特定日期的行键,您也可以从行键 productA#model2#1676376000 开始对 N 行执行正向扫描,然后从同一起始行开始对相同数量的行执行反向扫描。通过这两次扫描,您可以了解给定时间之前和之后的价格。

过滤后的读取

如果您只需要包含特定值的行或部分行,则可以对读取请求使用过滤条件。过滤条件可让您对所需数据进行高度选择。

过滤条件还可以让您确保读取的数据符合表格使用的垃圾回收政策。如果您经常将带时间戳的新单元写入现有列,则此方法特别有用。由于垃圾回收最多可能需要一周的时间来移除过期数据,因此使用时间戳范围过滤条件读取数据可以确保您读取的数据不会超出所需数量。

过滤条件概览详细说明了您可以使用的过滤条件类型。使用过滤条件可显示多种语言版本的示例。

从已获授权的视图读取数据

如需从已获授权的视图读取数据,您必须使用以下任一方法:

  • gcloud CLI
  • Java 版 Bigtable 客户端

其他 Bigtable 客户端库尚不支持视图访问。

支持调用 Bigtable Data API 的 ReadRowsSampleRowKeys 方法的任何方法。在创建客户端时,您需要提供已获授权的视图 ID 以及表 ID。

从连续具体化视图中读取数据

您可以使用 SQL 或 ReadRows Data API 调用从持续性具体化视图读取数据。持续性物化视图是只读的。物化视图中的数据的类型取决于定义它的查询

SQL

如需使用 SQL 从持续性具体化视图读取数据,您可以使用 Bigtable Studio 查询编辑器或支持 SQL 查询的客户端库之一。

SQL 会自动将查询结果显示为类型化列,因此您无需在查询中处理编码。

Data API

如果您打算通过 Bigtable 的某个客户端库中的 ReadRows 调用从持续性具体化视图中读取数据,则应查看用于定义该视图的 SQL 查询。请注意视图是否定义了 _key 列(建议为要使用 ReadRows 读取的视图定义此列),以及是否包含 _timestamp 列。

您还必须知道每列的类型,并在应用代码中解码列数据。

连续具体化视图中的汇总值是根据视图定义中列的输出类型,使用下表中所述的编码进行存储。

类型 编码
布尔值 1 字节值,1 = 真,0 = 假
BYTES 无编码
INT64(或 INT、SMALLINT、INTEGER、BIGINT、TINYINT、BYTEINT) 64 位大端字节序
FLOAT64 64 位 IEEE 754,不包括 NaN 和 +/-inf
STRING UTF-8
时间/时间戳 一个 64 位整数,表示自 Unix 纪元起的微秒数(与 GoogleSQL 一致)
如需了解详情,请参阅 Data API 参考文档中的 编码

除了了解视图中每列的类型之外,您还需要知道列族和列限定符。默认列族称为 default,列限定符是定义查询中指定的别名。例如,请考虑使用以下查询定义的连续具体化视图:

SELECT
  _key,
  SUM(clicks) AS sum_clicks
FROM
  mytable
GROUP BY
  sum_clicks

使用 ReadRows 查询视图时,您需要提供列族 default 和列限定符 sum_clicks

读取和性能

使用过滤条件的读取比不使用过滤条件的读取速度更慢,并且会使 CPU 利用率提高。另一方面,它们可以通过限制返回的数据量来显著减少您使用的网络带宽。 一般来说,您应使用过滤条件来控制吞吐量效率,而不是延迟时间。

如果要优化读取性能,请考虑以下策略:

  1. 尽可能限制行集。要改善首字节时间和总查询延迟时间,第一步就是限制节点必须扫描的行数。如果您不限制行集,则 Bigtable 几乎必须扫描整个表格。因此,我们建议您设计架构,以便让最常见的查询以这种方式运行。

  2. 如需在限制行集后进行其他性能调整,请尝试添加基本过滤条件。限制列集或返回的版本数通常不会增加延迟时间,并且有时有助于 Bigtable 更有效地查找每行中过往的不相关数据。

  3. 如果您希望在执行前两种策略之后微调读取性能,请考虑使用更复杂的过滤条件。您可能需要尝试此操作的原因如下:

    • 您仍会收到大量不需要的数据。
    • 您希望通过将查询下推到 Bigtable 中来简化应用代码。

    但请注意,要求条件、交错或正则表达式匹配大多数值的过滤条件如果让大多数扫描的数据通过,则往往利大于弊。这种弊端的表现形式为集群中 CPU 使用率增加,而客户端并不会出现大量节省。

除了这些策略之外,请避免在单个读取请求中读取大量非连续行键或行范围。当您在单个请求中请求数百个行键或行范围时,Bigtable 会扫描表并按顺序读取所请求的行。这种并行性影响会影响总体并造成任何命中热节点可增加尾巴延迟时间。请求的行范围越多,完成读取所需的时间就越长。如果此延迟不可接受,则您应改为发送多个并发请求,每个请求检索较少的行范围。

一般来说,读取单个请求中的更多行范围会优化吞吐量,但不会优化延迟时间。减少多个并发请求中的行数范围可优化延迟,但优化吞吐量。如需找到延迟时间与吞吐量之间的适当平衡,这取决于应用的要求,并可通过在一个请求中调整并发读取请求计数和行数范围来实现。

大型行

Bigtable 会强制执行以下针对大行施加的限制:

  • 行大小上限为 256 MB。如果需要读取已超出限制的行,您可以对请求进行分页并使用 cells per row limit 过滤条件cells per row offset 过滤条件。请注意,如果写入在分页读取请求之间到达该行,则该读取可能不是原子操作。

  • ReadRows API 调用的大小上限为 512 KB。如果超出此限制,Bigtable 会返回 INVALID_ARGUMENT 错误。

后续步骤