读取

本页面介绍了可以发送到 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 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 过滤条件。请注意,如果写入在分页读取请求之间到达该行,则该读取可能不是原子操作。

后续步骤