读取

本页面介绍了可以发送到 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++ 2.18.0 版或更高版本的 Bigtable 客户端库
  • 适用于 Go 1.21.0 或更高版本的 Bigtable 客户端库
  • 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。

读取和性能

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

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

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

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

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

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

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

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

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

大型行

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

后续步骤