对象表(Object Table)
对象表(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 和检索能力,对非结构化数据进行智能查询与分析。 |
整体架构
计算流程
前提条件
集群的产品系列为企业版、基础版或湖仓版。
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'];参数说明
参数名 | 类型 | 是否必填 | 默认值 | 描述 |
| VARCHAR | 是 | 无 | 文件所在的 OSS 路径目录,对象表会对该目录下的文件进行元数据抽取。例如: |
| VARCHAR | 是 | 无 | OSS 的 Endpoint。每个地域的域名详情请参见 地域和Endpoint。例如: |
| VARCHAR | 否 | 系统默认角色 | 阿里云 RAM 角色的 ARN。例如: |
| VARCHAR | 否 |
| 存储类型。 |
| VARCHAR | 否 |
| 分布键。 |
| VARCHAR | 否 |
| 聚簇索引。 |
| VARCHAR | 否 |
| 存储策略,支持 |
| VARCHAR | 否 | 无 | 分区键。 |
| VARCHAR | 否 |
| 分区键格式,当前仅支持 |
| INT | 否 | 0(不淘汰) | 表数据生命周期,单位为天。 |
对象表固定字段
对象表的字段结构固定,不支持用户自定义列。各字段含义如下:
列名 | 类型 | 描述 |
| VARCHAR | OSS 中文件的完整路径。 |
| VARCHAR | 文件的 etag,在每个 Object 生成时创建,具备唯一性,用于标识文件内容。 |
| LONG | 文件大小,可能为空。 |
| VARCHAR | 文件的 MD5 哈希值,可能为空。 |
| JSON | 详细的元数据信息,可使用 JSON 函数解析。包含以下字段:
|
| JSON | 自定义的 metadata 信息。 |
DDL 操作限制
对象表支持部分 DDL 操作,具体限制如下:
DDL 语句 | 操作说明 | 是否支持 |
| 重命名对象表。 | 是 |
| 删除对象表。开启回收站后,删除的对象表会进入回收站。 | 是 |
| 添加索引。 | 是 |
| 删除索引。 | 是 |
| 清空对象表数据。 | 是 |
| 查看表信息。 | 否 |
| 添加列。 | 否 |
| 删除列。 | 否 |
| 修改列类型。 | 否 |
| 修改列名称和类型。 | 否 |
数据查询
对象表创建并刷新后,可以像查询普通表一样对其进行查询。metadata 和 extra 字段为 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 数据并授权访问
将待解析的 PDF 文件上传至 OSS Bucket 的指定目录下。例如:
oss://pdf-oss-bj/ai/pdf-test/说明对象表会自动读取指定 URI 目录下的所有文件元数据,无需逐个注册文件。
示例数据
本文PDF示例文件(sample.pdf)是一个典型的 PDF 发票样例文件,包含键值对和表格两种核心数据结构。

配置 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_schema 和 form_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>}'
);参数说明
参数名 | 类型 | 是否必填 | 说明 |
| STRING | 否 | 指定使用的模型名称。若留空,默认使用内置的 |
| STRING | 是 | 待解析 PDF 文件的完整 OSS 路径。示例: |
| INTEGER | 是 | 指定待解析的页面索引,从 1 开始计数。 |
| INTEGER | 否 | 函数执行的超时时间,单位为秒。默认值为 300 秒。 |
返回结果
函数返回一个 JSON 字符串,包含以下三类信息:
| 说明 | 示例字段 |
| 文件元数据,如文件名、大小、页数等。 |
|
| 从文档中提取的键值对(Key-Value)信息。 |
|
| 从文档中提取的表格数据,以 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 文件写入时,可以通过增量物化视图自动完成新增文件的解析,无需重复处理已有文件。
开启对象表 Binlog。
ALTER TABLE object_table_test BINLOG = true;创建增量物化视图,设置自动刷新间隔。
说明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;