对象表(Object Table)

更新时间:
复制为 MD 格式

对象表(Object Table)是AnalyticDB for MySQL中面向非结构化数据的只读元数据表,用户不可直接修改表中数据。通过对象表,您可以将存储在对象存储 OSS 中的非结构化数据(如PDF、PPT、图像、音视频、日志/事件流等)映射为数据库中可查询的表,自动抽取文件元数据并联动 AI 模型完成语义理解,实现非结构化数据的全链路加工、检索与分析。

功能概述

核心能力

在 AI 驱动的数据智能时代,企业需要释放非结构化数据的价值。对象表提供以下核心能力:

  • 以表的形式读取 OSS 中的非结构化数据(PDF、图片、PPT 等),自动抽取文件元数据。

  • 结合物化视图、ETL 和 AI Function 对非结构化数据进行加工。支持对非结构化数据进行 Embedding 并存储至AnalyticDB for MySQL,无需调用外部 Embedding 算法,同时可增量识别文件变化,减少重复计算。

  • 结合 AI Function(如 ai_embed)对非结构化数据进行推理和分类,也可结合向量检索与全文检索实现双路召回,满足非结构化数据的分析和搜索需求。

  • 支持将非结构化数据的分析结果与AnalyticDB for MySQL中的结构化数据进行联接查询,打通结构化与非结构化数据的分析链路。

通过对象表结合 AI Function 等能力,数据无需出库,无需调用外部服务,即可在AnalyticDB for MySQL内完成 OSS 上非结构化数据的全链路加工、检索与分析,提升数据安全性的同时拓宽业务的数据分析范围。

应用场景

场景

说明

非结构化数据感知

感知 OSS 上非结构化数据的变化,通过刷新(Refresh)操作获取最新的文件元数据信息。

数据加工与 ETL

结合物化视图或 ETL,增量或全量调用 AI Function 对非结构化数据进行加工,将结果写入AnalyticDB for MySQL表。

数据检索与分析

结合 AI Function 和检索能力,对非结构化数据进行智能查询与分析。

整体架构

image

计算流程

image

前提条件

  • 集群的产品系列为企业版、基础版或湖仓版

  • AnalyticDB for MySQL集群内核版本为3.2.8及以上版本。

    说明

    云原生数据仓库AnalyticDB MySQL控制台集群信息页面,配置信息区域,查看和升级内核版本。若集群已是最新默认基线版本但仍需升级,请通过钉钉联系阿里云服务支持处理(钉钉账号:x5v_rm8wqzuqf)。

语法

创建对象表

对象表是专为读取非结构化数据而设计的表,建表时无需指定列,对象表拥有固定的列结构。对象表创建后,必须执行一次刷新对象表操作才能查询到数据。

重要

单张对象表支持的最大 Key 数量为 5000 万。

CREATE OBJECT TABLE [schema_name.]object_table_name
WITH (
    uri = 'oss://my-bucket/my-uri/',
    endpoint = 'oss-xxxx.aliyuncs.com',
    [role_arn = 'acs:ram::12345678****:role/ADB-OSS-Reader',]
    [storage_type = '[oss | s3',]
    [distributed_key = 'columnName[,...]]',]
    [clustered_key = '[columnName{:asc}] [,...]]',]
    [storage_policy = '[hot | cold]',]
    [partition_column = 'columnName',]
    [partition_column_format = 'YYYYMMDD',]
    [lifecycle = N]
) [COMMENT 'object table'];

参数说明

参数名

类型

是否必填

默认值

描述

uri

VARCHAR

文件所在的 OSS 路径目录,对象表会对该目录下的文件进行元数据抽取。例如:oss://bucket/dir

endpoint

VARCHAR

OSS 的 Endpoint。每个地域的域名详情请参见 地域和Endpoint。例如:oss-cn-hangzhou-internal.aliyuncs.com

role_arn

VARCHAR

系统默认角色

阿里云 RAM 角色的 ARN。例如:acs:ram::12345678****:role/role-name。如不指定,系统将使用默认的 RAM 角色。您可登录 RAM 控制台,在身份管理 > 角色页面获取角色 ARN 信息。

storage_type

VARCHAR

oss

存储类型。

distributed_key

VARCHAR

uri

分布键。

clustered_key

VARCHAR

uri

聚簇索引。

storage_policy

VARCHAR

hot

存储策略,支持 hot(热存储)和 cold(冷存储)。

partition_column

VARCHAR

分区键。

partition_column_format

VARCHAR

%Y%m%d

分区键格式,当前仅支持 DATE_FORMAT 函数格式。

lifecycle

INT

0(不淘汰)

表数据生命周期,单位为天。

对象表固定字段

对象表的字段结构固定,不支持用户自定义列。各字段含义如下:

列名

类型

描述

uri

VARCHAR

OSS 中文件的完整路径。

etag

VARCHAR

文件的 etag,在每个 Object 生成时创建,具备唯一性,用于标识文件内容。

size

LONG

文件大小,可能为空。

md5_hash

VARCHAR

文件的 MD5 哈希值,可能为空。

metadata

JSON

详细的元数据信息,可使用 JSON 函数解析。包含以下字段:

  • uri(object的路径)

  • etag(唯一的object标识符)

  • size(文件大小)

  • last_modified_at(最后修改时间)

  • owner_name(文件 Owner)

  • provider(存储提供方,如 OSS)

  • endpoint(OSS Endpoint)

  • object_table_id(对象表 ID)

  • role_arn(RAM 角色 ARN)

extra

JSON

自定义的 metadata 信息。

DDL 操作限制

对象表支持部分 DDL 操作,具体限制如下:

DDL 语句

操作说明

是否支持

ALTER OBJECT TABLE [IF EXISTS] <table_name> RENAME TO <new_name>;

重命名对象表。

DROP OBJECT TABLE [IF EXISTS] <table_name> [FORCE];

删除对象表。开启回收站后,删除的对象表会进入回收站。

ALTER OBJECT TABLE <table_name> ADD INDEX index_name(index_column) [WITH options];

添加索引。

ALTER OBJECT TABLE <table_name> DROP INDEX index_name;

删除索引。

TRUNCATE TABLE <table_name>;

清空对象表数据。

SHOW CREATE OBJECT TABLE <table_name>;

查看表信息。

ALTER OBJECT TABLE <table_name> ADD COLUMN ...;

添加列。

ALTER OBJECT TABLE <table_name> DROP COLUMN ...;

删除列。

ALTER OBJECT TABLE <table_name> MODIFY COLUMN ...;

修改列类型。

ALTER OBJECT TABLE <table_name> CHANGE COLUMN ...;

修改列名称和类型。

数据查询

对象表创建并刷新后,可以像查询普通表一样对其进行查询。metadataextra 字段为 JSON 类型,可使用 JSON 函数进行解析。

-- 查询所有数据
SELECT * FROM <object_table_name>;

-- 通过 JSON 函数提取 metadata 中的字段
SELECT uri, etag, json_extract(metadata, '$.uri') FROM <object_table_name>;

-- 使用简写语法提取 JSON 字段
SELECT metadata->>'$.uri' FROM <object_table_name>;

查询表结构信息

-- 查看对象表的列定义
DESC <object_table_name>;

-- 通过 INFORMATION_SCHEMA 查询列信息
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '<object_table_name>';

-- 查看对象表的索引信息
SHOW INDEX FROM <object_table_name>;

刷新对象表

对象表创建后,必须执行一次刷新操作才能查询到数据。当前仅支持手动刷新。

REFRESH OBJECT TABLE [<schema_name>.]<table_name>;

开启 Binlog

对象表支持开启 Binlog,开启后可结合增量物化视图实现增量数据刷新。

ALTER OBJECT TABLE [<schema_name>.]<table_name> SET binlog=true;

使用示例

场景说明

某企业将大量 PDF 格式的发票文件存储在 OSS 中,需要:

  • 通过 SQL 统一管理和查询这些 PDF 文件的元数据信息。

  • 利用 AI 能力自动提取发票中的商品明细(表格)和关键字段(如开票日期、发票号、金额等)。

  • 通过物化视图将提取结果持久化,支持后续的检索和分析。

步骤一:开通AI Function环境

请提交工单联系技术开通AI Function环境。

步骤二:准备 OSS 数据并授权访问

  1. 将待解析的 PDF 文件上传至 OSS Bucket 的指定目录下。例如:

    oss://pdf-oss-bj/ai/pdf-test/
    说明

    对象表会自动读取指定 URI 目录下的所有文件元数据,无需逐个注册文件。

    示例数据

    本文PDF示例文件(sample.pdf)是一个典型的 PDF 发票样例文件,包含键值对和表格两种核心数据结构。

    image.png

  2. 配置 RAM 授权

    AnalyticDB for MySQL访问 OSS 需要通过 RAM 角色授权:

    • 同账号场景:如果AnalyticDB for MySQL实例和 OSS Bucket 在同一阿里云账号下,可以不指定 role_arn,系统将自动使用内置的服务角色完成授权。

    • 跨账号场景:需要在 RAM 控制台创建角色并授予 OSS 读取权限,获取对应的 ARN。详细步骤请参见跨账号授权

步骤三(可选):提取 PDF Schema

在正式解析之前,建议先对一个 PDF 文件进行 Schema 探测,了解文件中包含的表格和表单结构,以便后续精确提取。

SELECT ai_pdf_extract(
  'qwen35_plus',
  'oss://my-bucket/invoices/invoice_001.pdf',
  '{"page_index": 1}'
);

从返回的 JSON 结果中,您可以获取到该 PDF 的 table_schemaform_schema,并在后续查询中复用,从而提升解析效率。

步骤四:创建对象表

  • 同账号场景:无需指定 role_arn(不指定则使用系统自带的 role_arn)。

    CREATE OBJECT TABLE object_table_test WITH (
      uri = 'oss://pdf-oss-bj/ai/pdf-test/',-- oss资源对应目录
      endpoint = 'oss-cn-beijing-internal.aliyuncs.com'-- oss资源endpoint
    );
  • 跨账号场景:需要额外指定 role_arn

    CREATE OBJECT TABLE object_table_test WITH (
      uri      = 'oss://my-bucket/invoices/',
      endpoint = 'oss-cn-hangzhou-internal.aliyuncs.com',
      role_arn = 'acs:ram::1234567890:role/adb-oss-reader'
    );

步骤五:刷新对象表

对象表创建后必须手动执行一次刷新,才能查询到数据。

-- 刷新对象表
REFRESH OBJECT TABLE object_table_test;

-- 查询刷新任务状态
SELECT * FROM INFORMATION_SCHEMA.kepler_meta_refresh_object_table_job
ORDER BY start_time DESC LIMIT 10;

-- 查询对象表数据
SELECT * FROM object_table_test LIMIT 10;

步骤六:AI 智能解析 PDF 内容

对象表可以结合 AI Function 对 PDF 的内容进行检索和推理。以下示例展示三种查询方式。

使用ai_pdf_extract函数直接查询(快速验证)

此方式返回原始 JSON 结果,适合在调试阶段快速查看 AI 解析的完整输出。

语法

SELECT ai_pdf_extract(
  <model_name>,
  <file_url>,
  '{"page_index": <page_index>, "timeout": <timeout>}'
);

参数说明

参数名

类型

是否必填

说明

model_name

STRING

指定使用的模型名称。若留空,默认使用内置的 qwen3.5-plus 模型。

file_url

STRING

待解析 PDF 文件的完整 OSS 路径。示例:oss://<bucket>/path/sample.pdf

page_index

INTEGER

指定待解析的页面索引,从 1 开始计数。

timeout

INTEGER

函数执行的超时时间,单位为秒。默认值为 300 秒。

返回结果

函数返回一个 JSON 字符串,包含以下三类信息:

type

说明

示例字段

metadata

文件元数据,如文件名、大小、页数等。

filenamesizepage_counturl

form

从文档中提取的键值对(Key-Value)信息。

company_nameinvoice_numberamount_due

table

从文档中提取的表格数据,以 JSON 数组形式返回。

列名和行数据

示例

SELECT ai_pdf_extract(
  'qwen35_plus',
  metadata,
  '{"page_index": 1, "timeout": 300}'
)
FROM object_table_test
LIMIT 1;

CTE + JSON 解析(推荐,适合提取结构化字段)

示例

WITH pdf_data AS (
  SELECT
    ai_pdf_extract(
      'qwen35_plus',
      metadata,
      '{"page_index": 1, "schema":{
        "table_schema":[
          {"original_name":"DESCRIPTION","standard_name":"description","field_type":"string"},
          {"original_name":"RATE","standard_name":"rate","field_type":"number"},
          {"original_name":"QTY","standard_name":"qty","field_type":"number"},
          {"original_name":"AMOUNT","standard_name":"amount","field_type":"number"}
        ],
        "form_schema":[
          {"original_name":"Billed To","standard_name":"billed_to","field_type":"string"},
          {"original_name":"Invoice Number","standard_name":"invoice_number","field_type":"string"},
          {"original_name":"Date Issued","standard_name":"date_issued","field_type":"date"},
          {"original_name":"Amount Due","standard_name":"amount_due","field_type":"number"},
          {"original_name":"Total","standard_name":"total","field_type":"number"}
        ]
      }, "timeout": 300}'
    ) AS result
  FROM object_table_test
)
SELECT
  JSON_UNQUOTE(JSON_EXTRACT(result, '$.data[2].content.filename'))          AS file_name,
  JSON_UNQUOTE(JSON_EXTRACT(result, '$.data[2].content.size'))              AS file_size,
  JSON_UNQUOTE(JSON_EXTRACT(result, '$.data[2].content.creation_date'))     AS create_date,
  JSON_UNQUOTE(JSON_EXTRACT(result, '$.data[2].content.modification_date')) AS modify_date,
  JSON_UNQUOTE(JSON_EXTRACT(result, '$.data[2].content.page_count'))        AS page_count
FROM pdf_data;
说明

schema 参数中的 table_schema 对应 PDF 中的表格列,form_schema 对应 PDF 中的键值对字段。提供 Schema 后,AI 模型会依据指定结构进行精确提取,结果更加准确且速度更快。

子查询 + LATERAL VIEW(适合展开表格行数据)

示例

SELECT
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.description')) AS description,
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.rate'))        AS rate,
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.qty'))         AS qty,
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.amount'))      AS amount
FROM (
  SELECT ai_pdf_extract(
    'qwen35_plus',
    metadata,
    '{"page_index": 1, "schema":{
      "table_schema":[
        {"original_name":"DESCRIPTION","standard_name":"description","field_type":"string"},
        {"original_name":"RATE","standard_name":"rate","field_type":"number"},
        {"original_name":"QTY","standard_name":"qty","field_type":"number"},
        {"original_name":"AMOUNT","standard_name":"amount","field_type":"number"}
      ]
    }, "timeout": 300}'
  ) AS result
  FROM object_table_test
) pdf_data
LATERAL VIEW EXPLODE(JSON_EXTRACT(result, '$.data[0].content')) t AS row_data;

返回示例

description

rate

qty

amount

Consulting Services

150.00

10

1500.00

Software License

500.00

2

1000.00

Technical Support

75.00

20

1500.00

说明

LATERAL VIEW EXPLODE 用于将 JSON 数组中的每条表格行展开为独立的结果行,适合处理 PDF 表格数据。

步骤七:通过物化视图持久化解析结果

对于需要反复查询的场景,建议将 AI 解析结果写入物化视图,避免重复调用 AI 模型。

全量物化视图

CREATE MATERIALIZED VIEW invoice_mv_full
REFRESH COMPLETE ON DEMAND
AS
SELECT
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.description')) AS description,
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.rate'))        AS rate,
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.qty'))         AS qty,
  JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.amount'))      AS amount
FROM (
  SELECT ai_pdf_extract(
    'qwen35_plus',
    metadata,
    '{"page_index": 1, "schema":{
      "table_schema":[
        {"original_name":"DESCRIPTION","standard_name":"description","field_type":"string"},
        {"original_name":"RATE","standard_name":"rate","field_type":"number"},
        {"original_name":"QTY","standard_name":"qty","field_type":"number"},
        {"original_name":"AMOUNT","standard_name":"amount","field_type":"number"}
      ]
    }, "timeout": 300}'
  ) AS result
  FROM object_table_test
) pdf_data
LATERAL VIEW EXPLODE(JSON_EXTRACT(result, '$.data[0].content')) t AS row_data;

-- 查询物化视图
SELECT * FROM invoice_mv_full;

增量物化视图

当 OSS 中持续有新的 PDF 文件写入时,可以通过增量物化视图自动完成新增文件的解析,无需重复处理已有文件。

  1. 开启对象表 Binlog。

    ALTER TABLE object_table_test BINLOG = true;
  2. 创建增量物化视图,设置自动刷新间隔。

    说明

    AI Function 的处理耗时较长,建议将增量刷新间隔设置为 5 分钟或更长,避免刷新任务堆积。

    -- 创建只缓存 AI 结果的物化视图
    CREATE MATERIALIZED VIEW invoice_mv_cache
    REFRESH FAST NEXT now() + INTERVAL 5 MINUTE
    AS
    SELECT 
        uri, -- 包含主键,确保增量刷新能识别变更
        ai_pdf_extract(
            'qwen35_plus',
            metadata,
            '{"page_index": 1, "schema":{
              "table_schema":[
                {"original_name":"DESCRIPTION","standard_name":"description","field_type":"string"},
                {"original_name":"RATE","standard_name":"rate","field_type":"number"},
                {"original_name":"QTY","standard_name":"qty","field_type":"number"},
                {"original_name":"AMOUNT","standard_name":"amount","field_type":"number"}
              ]
            }, "timeout": 300}'
        ) AS ai_result
    FROM object_table_test;
    
    -- 创建虚拟视图 (进行“实时”展开)
    CREATE VIEW invoice_mv_incremental_view AS
    SELECT
        JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.description')) AS description,
        CAST(JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.rate')) AS DOUBLE) AS rate,
        CAST(JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.qty')) AS DOUBLE) AS qty,
        CAST(JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.amount')) AS DOUBLE) AS amount
    FROM invoice_mv_cache
    LATERAL VIEW EXPLODE(
        -- 将数组解析出来
        CAST(JSON_EXTRACT(ai_result, '$.data[0].content') AS ARRAY<JSON>)
    ) t AS row_data;
    
    SELECT * FROM invoice_mv_cache;
    SELECT * FROM invoice_mv_incremental_view;

步骤八(可选):ETL 增量加工

除物化视图外,您还可以通过 ETL 方式,基于对象表的 last_modified_at 列筛选增量数据,将 AI 解析结果写入普通表。

说明

ETL 方式可以灵活控制增量条件和写入目标,适合需要自定义加工逻辑的场景。您也可以结合AnalyticDB for MySQL的定时任务能力,实现自动化的增量调度。

-- 创建目标表存储解析结果
CREATE TABLE invoice_parsed_data (
  uri         VARCHAR NOT NULL,
  description VARCHAR,
  rate        DECIMAL(10,2),
  qty         INT,
  amount      DECIMAL(10,2),
  parsed_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (uri, description)
) DISTRIBUTE BY HASH(uri);

-- 增量写入:仅处理最近一天新增或变更的文件
REPLACE INTO invoice_parsed_data (uri, description, rate, qty, amount)
SELECT
  CAST(pdf_data.file_uri AS VARCHAR) as uri,
  CAST(JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.description')) AS VARCHAR) AS description,
  CAST(JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.rate')) AS DECIMAL(10,2)) AS rate,
  CAST(JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.qty')) AS int) AS rate,
  CAST(JSON_UNQUOTE(JSON_EXTRACT(row_data, '$.amount')) AS DECIMAL(10,2)) AS amount
FROM (
  SELECT
    uri AS file_uri,
    ai_pdf_extract(
      'qwen35_plus',
      metadata,
      '{"page_index": 1, "schema":{
        "table_schema":[
          {"original_name":"DESCRIPTION","standard_name":"description","field_type":"string"},
          {"original_name":"RATE","standard_name":"rate","field_type":"number"},
          {"original_name":"QTY","standard_name":"qty","field_type":"number"},
          {"original_name":"AMOUNT","standard_name":"amount","field_type":"number"}
        ]
      }, "timeout": 300}'
    ) AS result
  FROM object_table_test
  WHERE last_modified_at >= DATE_SUB(NOW(), INTERVAL 1 DAY)
) pdf_data
LATERAL VIEW EXPLODE(JSON_EXTRACT(result, '$.data[0].content')) t AS row_data;