Schema 转换与数据类型映射

更新时间:
复制 MD 格式

选定了目标表格式后。本文档在此基础上完成 BigQuery schema 的翻译,即列级类型映射、复杂类型(STRUCT、ARRAY、MAP)转换、分区策略转换。

目标

  • 把任何 BigQuery 标量类型对应到 MaxCompute 等价类型,并知道精度和时区上何时需要特别关注。

  • RECORD / STRUCTARRAY<STRUCT> 列翻译成 MaxCompute DDL,包含嵌套场景。

  • 使用 MaxCompute 原生 UNNEST,以与 BigQuery 一致的查询形式展开 ARRAY<STRUCT> 列。

能力说明

标量类型映射

BigQuery 类型

MaxCompute 类型

说明

INT64

BIGINT

均为 64 位有符号整数

FLOAT64

DOUBLE

均为 64 位 IEEE 754

NUMERIC

DECIMAL(38, 9)

BigQuery NUMERIC 固定精度 38 位 / 9 位小数

NUMERIC(p, s)

DECIMAL(p, s)

指定精度时直接映射;要求 p ≤ 38

NUMERIC(p)

DECIMAL(p, 0)

仅指定整数精度时小数位为 0

BIGNUMERIC

DECIMAL(38, 18)

默认精度 (38, 18),可由用户配置

BIGNUMERIC(p, s)

p ≤ 38 且 s ≤ 30

DECIMAL(p, s)

精度和小数位均在 MaxCompute 范围内时直接映射

BIGNUMERIC(p, s)

p > 38 或 s > 30

不支持

MMS 无法自动迁移。迁移前需在源侧审计:SELECT COUNT(*) WHERE ABS(col) >= 1e29

BOOLEAN

BOOLEAN

完全兼容

STRING

STRING

兼容,MaxCompute 单值上限 8 MB

BYTES

BINARY

兼容

DATE

DATE

日粒度,兼容

DATETIME

TIMESTAMP_NTZ

BigQuery DATETIME 无时区,映射到 TIMESTAMP_NTZ 保留原始值

TIMESTAMP

TIMESTAMP_NTZ

BigQuery TIMESTAMP 内部以 UTC 存储绝对时间点。迁移到 TIMESTAMP_NTZ 后,所有值以 UTC 存储,无时区语义。查询侧如需按业务时区展示,使用 FROM_UTC_TIMESTAMP(col, 'Asia/Shanghai') 转换

TIME

BIGINT

MaxCompute 无独立 TIME 类型。BigQuery TIME 以午夜零点以来的微秒数存储(范围 0 ~ 86,399,999,999),直接映射为 BIGINT。GoTerra 之后新增的 TIME_* 函数可处理微秒编码

GEOGRAPHY

GEOGRAPHY

MaxCompute 原生支持 GEOGRAPHY 类型

INTERVAL

INTERVAL

MaxCompute 支持 INTERVAL_YEAR_MONTH / INTERVAL_DAY_TIME

RANGE

STRING

MaxCompute 无原生 RANGE 类型;以字符串表示区间边界

  • 精度注意事项:

    • BIGNUMERIC(p, s) 中 p ≤ 38 且 s ≤ 30 时直接映射为 DECIMAL(p, s);p > 38 或 s > 30 时可通过 DECIMAL256(p, s) 映射,覆盖最高 76 位总精度;

    • 超过 76 位的值无法迁移,迁移前检查:SELECT COUNT(*) FROM t WHERE CAST(col AS STRING) LIKE '%.%' AND LENGTH(REGEXP_EXTRACT(CAST(col AS STRING), r'\d+')) > 76

  • 时区注意事项:

    • BigQuery TIMESTAMP 内部以 UTC 存储绝对时间点,按用户时区展示。迁到 TIMESTAMP_NTZ 后,值仍以 UTC 存储,但不再携带时区语义 SET odps.sql.timezone 对 TIMESTAMP_NTZ 列无效。查询侧如需按业务时区展示,显式转换:FROM_UTC_TIMESTAMP(col, 'Asia/Shanghai')

    • BigQuery DATETIME 是无时区的:2026-07-14 09:00:00 不带时区。映射到 TIMESTAMP_NTZ,保留原始值,不做隐式 UTC 偏移。

复杂类型映射

BigQuery 类型

统一映射

说明

JSON

JSON

均为原生类型

ARRAY<T>

ARRAY<T>

元素类型按标量映射表递归转换。BigQuery 不允许 ARRAY<ARRAY<T>> 直接嵌套,MaxCompute 同理

STRUCT<...>

STRUCT<...>

字段分隔符不同:BigQuery <name type>,MaxCompute <name : type>。BigQuery 嵌套上限 15 层,MaxCompute 20 层

ARRAY<STRUCT<...>>

ARRAY<STRUCT<...>>

BigQuery 最常用的组合。MaxCompute 已原生支持 UNNEST 展开,语法基本一致

ARRAY<JSON>

ARRAY<STRING>

MaxCompute 不支持复杂类型内嵌 JSON,降级为 STRING

STRUCT 内含 JSON 字段

不支持

如 STRUCT<a: JSON> 不可迁移,需源侧预处理

STRUCT 与嵌套 STRUCT

两个平台都支持任意深度的 STRUCT 嵌套,但在 DDL 语法、构造方式、NULL 处理和 Schema 演进方面存在差异。

完整关于MaxCompute Struct 数据类型介绍请参考:STRUCT数据类型

DDL 语法

  • 字段分隔符:BigQuery 使用 <name type>,MaxCompute 使用 <name : type>

  • 尾逗号:两侧的 STRUCT<...> 内均不允许。

-- BigQuery
CREATE TABLE user_events (
  user_id INT64,
  device STRUCT<
    os      STRING,
    version STRING,
    model   STRING
  >
);

-- MaxCompute
CREATE TABLE user_events (
  user_id BIGINT,
  device  STRUCT<
    os      : STRING,
    version : STRING,
    model   : STRING
  >
) TBLPROPERTIES ("table.format.version" = "2");

DDL —— 3 层嵌套 STRUCT

-- MaxCompute
CREATE TABLE user_events (
  user_id BIGINT,
  device  STRUCT<
    os        : STRING,
    version   : STRING,
    hardware  : STRUCT<
      model  : STRING,
      cpu    : STRUCT<
        cores : INT,
        arch  : STRING
      >
    >
  >
) TBLPROPERTIES ("table.format.version" = "2");

嵌套深度上限

平台

STRUCT 最大嵌套深度

BigQuery

15

MaxCompute

20

MaxCompute 嵌套深度上限更大,任意 BigQuery STRUCT 层级都可以直接翻译。

注意,MaxCompute 单个 STRUCT 值(含所有嵌套字段)序列化后不应超过 1 MB,否则计算时可能触发 OOM。迁移前建议在 BigQuery 侧对字段大小进行估算。

字面量构造

BigQuery 提供三种 STRUCT 构造语法,MaxCompute 提供三种对应函数。

操作

BigQuery

MaxCompute

说明

命名式

STRUCT('ios' AS os, '17.0' AS version)

STRUCT('ios' AS os, '17.0' AS version)

语法一致。MaxCompute 称为 STRUCT EXPRESSION

位置式

STRUCT('ios', '17.0')

STRUCT('ios', '17.0')

BigQuery 字段匿名;MaxCompute 自动命名为 col1, col2

键值对式

STRUCT('ios' AS os, ...)

NAMED_STRUCT('os', 'ios', 'version', '17.0')

MaxCompute 的 NAMED_STRUCT 以 (name, value, name, value, ...) 形式传参

全表构造

SELECT AS STRUCT * FROM t

STRUCT(*) FROM t

将整行打包为 STRUCT

含 NULL 字段

STRUCT(NULL AS a, 2 AS b)

需 SET odps.sql.bigquery.compatible=true;

仅 STRUCT EXPRESSION 支持,STRUCT/NAMED_STRUCT 函数不支持 NULL

字段访问

t.device.os

t.device.os

完全相同

Schema 演进

  • BigQuery:SQL DDL 不支持对已有 STRUCT 内部增删改字段;但通过 bq CLI / API 如 update、 tables.patch 可以添加嵌套字段。删除和重命名任何方式都不支持。

  • MaxCompute:ALTER TABLE 不支持对已有 STRUCT 内部做增删改字段(与 BQ DDL 行为一致)。

ARRAY of STRUCT 展开

ARRAY<STRUCT>(例如 cart_items 列、event_params 列)是 BigQuery 最常用的结构之一。MaxCompute 已原生支持 UNNEST,提供三种展开模式,覆盖 BigQuery 的所有常见用法。

完整关于MaxCompute UNNEST使用说明请参考:UNNEST

DDL语法

-- BigQuery
CREATE TABLE orders (
  order_id INT64,
  items ARRAY<STRUCT<
    sku   STRING,
    qty   INT64,
    price NUMERIC
  >>
);

-- MaxCompute
CREATE TABLE orders (
  order_id BIGINT,
  items ARRAY<STRUCT<
    sku   : STRING,
    qty   : BIGINT,
    price : DECIMAL(38, 9)
  >>
) TBLPROPERTIES ("table.format.version" = "2");

模式 1:标量数组展开

-- BigQuery
SELECT tag
FROM products, UNNEST(tags) AS tag;

-- MaxCompute
SELECT tag
FROM products
JOIN UNNEST(products.tags) AS tag;

模式 2:STRUCT 数组展开(最常用)

STRUCT 数组展开后,每个 STRUCT 字段自动成为独立列,与 BigQuery 行为一致。

-- BigQuery
SELECT o.order_id, item.sku, item.qty, item.price
FROM orders o
CROSS JOIN UNNEST(o.items) AS item;

-- MaxCompute
SELECT o.order_id, item.sku, item.qty, item.price
FROM orders o
JOIN UNNEST(o.items) AS item;
-- 若需保留 items 为 NULL 或空数组的行,使用 LEFT JOIN UNNEST(...)。

MaxCompute 的 UNNEST 仅展开最外层 STRUCT 字段。若 ARRAY<STRUCT<..., sub STRUCT<...>>> 中存在内层 STRUCT,UNNEST 会把 sub 保留为单列,使用点符号访问其中字段(item.sub.field)。BigQuery 行为相同。

模式 3:JOIN UNNEST(带 ON 条件,MaxCompute 增强)

MaxCompute 的 JOIN UNNEST 支持 ON 等值条件,可以在展开的同时过滤元素,减少中间结果集。BigQuery 不支持此语法。

-- MaxCompute:展开 user 的 allowed_dept_ids,仅保留匹配当前部门的元素

SELECT u.user_id, dept_id AS allowed_dept_id
FROM user_configs u
JOIN UNNEST(u.allowed_dept_ids) AS dept_id
  ON dept_id = u.current_dept_id;

此语法在权限过滤、标签匹配等场景中比先展开再 WHERE 更高效。

元素位置

BigQuery 的 UNNEST(...) WITH OFFSET AS idx 返回元素位置。MaxCompute 通过 POSEXPLODE 提供该能力:

-- MaxCompute 中 BigQuery WITH OFFSET 的等价写法

SELECT o.order_id, idx, item.sku
FROM orders o
LATERAL VIEW POSEXPLODE(o.items) t AS idx, item;

增强嵌套列裁剪

BigQuery 默认对 STRUCT 列执行嵌套列裁剪,查询仅访问 device.os 时,引擎只读取 os 子列,不扫描整个 STRUCT。MaxCompute 也提供增强嵌套列裁剪能力。建议项目级别设置:

SETPROJECT odps.sql.nested.type.enable.enhanced.cp = true;

MaxCompute 增强嵌套列裁剪适用于以下复杂类型及其任意嵌套组合:

  • STRUCT<...>

  • ARRAY<STRUCT<...>>

  • MAP<STRING, STRUCT<...>>

  • 多层嵌套组合,如 ARRAY<STRUCT<tags: ARRAY<STRING>, meta: STRUCT<...>>>

生效范围:覆盖 SELECT、WHERE、JOIN、GROUP BY、窗口函数、CTE 和 UNNEST 等场景。

不触发增强裁剪的场景:以下情况引擎无法下推子字段裁剪,会读取完整复杂类型

场景

示例

SELECT *

SELECT * FROM t;(读取所有列,无裁剪空间)

引用完整 STRUCT 变量

SELECT device FROM events;(需要整个 STRUCT)

TO_JSON() 序列化

SELECT TO_JSON(device) FROM events;(需要完整结构用于序列化)

UNNEST 需完整元素

SELECT item FROM orders JOIN UNNEST(items) AS item;(item 是完整 STRUCT)

完整 MaxCompute 增强嵌套列裁剪能力请参考:增强版嵌套列裁剪功能