查询 Avro 数据

借助 GoogleSQL for Bigtable,您可以查询、过滤和投影 Bigtable 表存储的序列化 Apache Avro 记录中的各个字段。通过在 SQL 查询中引用 Avro 架构包,您可以将字节列转换为结构化 Avro 记录并提取嵌套字段。

在查询 Avro 字段之前,您必须在架构包中上传 Avro 架构,如创建和管理 Avro 架构中所述。如需了解 GoogleSQL 查询如何映射到 Bigtable 表架构,以及如何在 SQL 语句中引用列,请参阅 GoogleSQL for Bigtable 概览。

如需在 Java 中使用 GoogleSQL 查询 Avro 数据,请使用 Cloud Bigtable 客户端库中的 executeQuery 方法。如需查看使用客户端库运行 SQL 查询的示例,请参阅客户端库。

Avro 数据类型映射

将序列化 BYTES 转换为 Avro 记录时,GoogleSQL for Bigtable 会将 Avro 架构类型映射到 SQL 可访问的类型,如下所示:

Avro 类型 GoogleSQL 表示法 说明
int,long INT64 32 位和 64 位有符号整数会映射到 64 位整数。
float FLOAT32 单精度浮点值
double FLOAT64 双精度浮点值
boolean BOOL 布尔值(TRUE 或 FALSE)
string STRING Unicode 字符序列
bytes BYTES 原始字节序列
record 消息对象 使用点表示法(例如 record.field)访问嵌套字段。
enum ENUM 枚举符号集
array ARRAY 重复字段。Bigtable 不支持嵌套数组。
map<T> 键值对条目重复 Avro 映射具有 STRING 键。Bigtable 支持具有可为 null 的值的映射,例如 {"type": "map", "values": ["null", "string"]}。您可以使用 ARRAY_TRANSFORM 函数将映射转换为 ARRAY<STRUCT<key STRING, value T>>。
union 可以为 Null 的字段 Bigtable 会将包含 null 和一个非 null 类型的联合映射到标准可为 null 的字段。
fixed Bigtable 不支持 fixed 类型。 固定长度的字节序列。

示例数据

本页中的示例使用 ID 为 my_avro 的 Avro 架构包。此软件包在 com.example.billing 命名空间中包含以下 Transaction 记录架构:

{
  "type": "record",
  "namespace": "com.example.billing",
  "name": "Transaction",
  "fields": [
    {"name": "product_name", "type": "string"},
    {"name": "product_category", "type": "string"},
    {"name": "configs", "type": {"type": "map", "values": "string"}}
  ]
}

名为 table 的 Bigtable 表将序列化的 Avro 记录存储在 cf 列族和 product 列限定符 (cf['product']) 中:

行键 cf['product'] 列(存储为序列化 BYTES,为便于阅读,显示为 JSON)
row1 {"product_name": "Chips", "product_category": "yummy food", "configs": {"size": "large", "flavor": "BBQ"}}
row2 {"product_name": "Apple", "product_category": "yummy food", "configs": {}}
row3 {"product_name": "Book", "product_category": "reading", "configs": {"author": "Jane Doe"}}

示例查询

上传 Avro 架构软件包后,您可以在 GoogleSQL for Bigtable 中使用 CAST 运算符将 BYTES 值解释为 Avro 记录。

转换列和投影字段

如需将 BYTES 值转换为 Avro 记录,请按以下格式指定完整记录名称:

SCHEMA_BUNDLE_ID.FULLY_QUALIFIED_RECORD_NAME

替换以下内容:

  • SCHEMA_BUNDLE_ID:架构包的 ID
  • FULLY_QUALIFIED_RECORD_NAME:Avro 记录的全名,包括 Avro 架构中定义的命名空间,例如 com.example.billing.Transaction

如果指定的架构包或记录名称不存在,则查询会失败,并显示 INVALID_ARGUMENT 状态和 type not found 出错提示。如果提供的架构无法解析单元格字节,则查询会失败,并显示 FAILED_PRECONDITION 或 INVALID_ARGUMENT 状态。

以下查询会将 cf['product'] 列转换为 my_avro 架构包中的 com.example.billing.Transaction 记录,并投影 product_name 字段:

SELECT
  CAST(cf['product'] AS my_avro.com.example.billing.Transaction).product_name
FROM
  table;

查询将返回以下结果:

product_name (STRING)
芯片数
Apple
书籍

根据 Avro 字段进行过滤

您可以使用 WHERE 子句根据 Avro 记录中的字段值过滤行。

以下查询会过滤 product_category 字段等于 "yummy food" 的行:

SELECT
  CAST(cf['product'] AS my_avro.com.example.billing.Transaction).product_name
FROM
  table
WHERE
  CAST(cf['product'] AS my_avro.com.example.billing.Transaction).product_category = "yummy food";

查询将返回以下结果:

product_name (STRING)
芯片数
Apple

访问映射字段

您可以使用 ARRAY_TRANSFORM 函数将 Avro map 字段中的键值对投影为 STRUCT 元素数组。

以下查询会投影 product_name,并将 configs 映射字段转换为 STRUCT<key STRING, value STRING> 元素数组:

SELECT
  CAST(cf['product'] AS my_avro.com.example.billing.Transaction).product_name,
  ARRAY_TRANSFORM(
    CAST(cf['product'] AS my_avro.com.example.billing.Transaction).configs,
    e -> STRUCT(e.key, e.value)
  ) AS map_array
FROM
  table;

查询将返回以下结果:

product_name (STRING) map_array (ARRAY<STRUCT<key STRING, value STRING>>)
芯片数 [{"key": "size", "value": "large"}, {"key": "flavor", "value": "BBQ"}]
Apple []
书籍 [{"key": "author", "value": "Jane Doe"}]

与视图搭配使用

您可以在持续物化视图和逻辑视图中引用 Avro 架构包。

如果持续具体化视图或逻辑视图引用了 Avro 架构包,则您无法删除该包。在删除该 bundle 之前,您必须先删除引用该 bundle 的所有持续物化视图。对于引用该 bundle 的任何逻辑视图,您必须更新这些视图以移除引用,或者删除这些视图。

以下命令会创建一个持续具体化视图,用于按 product_name 汇总交易计数:

gcloud bigtable materialized-views create MATERIALIZED_VIEW_ID \
    --instance=INSTANCE_ID \
    --query="SELECT CAST(cf['product'] AS my_avro.com.example.billing.Transaction).product_name AS product, COUNT(*) AS transaction_count FROM table GROUP BY product;"

替换以下内容:

  • MATERIALIZED_VIEW_ID:引用架构包的持续具体化视图的 ID
  • INSTANCE_ID:Bigtable 实例的 ID

后续步骤