摘要:
Apache Doris 5.0 多模湖仓预告(1)|场景方案篇:智能驾驶与具身智能每天产生海量多模态数据,真正难的是从中快速找到高价值 Episode,并判断问题集中在哪些场景、版本与任务。本文介绍 Apache Doris + Lance 如何打通语义检索、结构化筛选与 OLAP 分析,在开放数据架构上实现难例挖掘、失败归因和训练评测闭环。
SelectDB 已提供支持 Lance Catalog 的商业预览版本。
作者:李文强,Apache Doris PMC 成员、SelectDB 多模湖仓负责人
自动驾驶汽车每天产生的视频、点云、车辆状态和模型输出,机器人每次任务则同时留下多路相机、关节状态、动作轨迹、语言指令与执行结果。对这些系统而言,困难早已不只是“把数据存下来”,而是能否从海量数据中快速回答一组决定模型迭代效率的问题:
哪些片段包含与本次事故相似的场景?
新模型在夜间、施工区或异形障碍物上的接管率是否变高?
哪类机器人任务最容易失败,失败前出现了哪些相似的视觉或动作模式?
如何把筛选出的高价值 Episode 交给标注、训练和回归评测?
传统数据仓库擅长聚合结构化事实,向量数据库擅长“以图搜图”,对象存储擅长低成本保存海量文件;但 Physical AI 需要把语义检索、结构化筛选、业务指标和原始证据放进同一条分析链路。
Apache Doris 对 Lance Catalog 的支持,为此提供了一种开放而直接的组合:Lance 负责承载面向 AI 的开放多模态数据集及其向量索引,Doris 直接查询这些数据,在一个 SQL 执行框架中完成条件下推、并行扫描、向量召回、全局 Top-K 和 OLAP 聚合。数据无需先搬进专用分析副本,AI 数据资产也不必被锁定在单一计算系统中。
一、为什么 Physical AI 需要“语义检索 + 分析”,而不只是向量检索
智能驾驶和具身智能的数据天然以 Episode 为中心。一个 Episode 不是单张图片,而是一段可还原的物理过程:环境被传感器观测,模型作出判断,控制系统执行动作,现实世界给出结果。
以智能驾驶为例,“找出与事故前 5 秒相似的画面”只是第一步。工程团队还需要继续限定车型、传感器版本、道路类型、天气、模型版本和时间范围,再比较这些候选片段中的接管率、误检率或规划偏差。具身智能同样如此:一次抓取失败既涉及视觉语义,也涉及任务类型、机械臂型号、策略版本、关节状态、动作轨迹和最终结果。
这意味着高价值数据发现至少包含三层计算:
用结构化条件把搜索空间收窄到正确的业务上下文;
用向量相似度发现标签体系尚未覆盖的相似场景;
用聚合、关联、排序和窗口分析,把候选片段转化为模型评测结论与可执行的数据集。
Lance 与 Doris 的互补性恰好位于这里:前者管理 AI 数据集、随机访问和向量索引,后者把检索结果放回可解释、可组合的 SQL 分析体系。
二、整体架构:Lance 管理 AI 数据资产,Doris 负责统一查询分析

【图 1】Apache Doris + Lance 在 Physical AI 数据架构中的位置
在这套架构中,上游继续使用 Lance SDK,Ray,Spark 等工具生成和维护 Lance Dataset,包括特征、Embedding、标签、模型输出以及已有的 Lance 向量索引;数据可位于本地文件系统、S3 兼容对象存储或 OSS。
Apache Doris 通过 Lance Catalog 发现数据集和 Schema,并在一次查询中固定快照、拆分 Fragment 或 Index Segment、并行执行扫描与检索,最后完成全局 Top-K 和 OLAP 计算。
Apache Doris 解决的是训练前后最容易被忽视的一层:让工程师、算法团队、业务分析和 Agent 能够以统一方式发现数据、验证模型、定位问题并构造下一轮训练集。
三、智能驾驶:从“找一段相似视频”到难例挖掘闭环
3.1 瓶颈不在采集,而在从海量数据中找到高价值场景
在自动驾驶研发中,难例挖掘(Hard Case Mining)是指从海量行车数据中发现模型容易误判、漏判,或者触发异常制动与人工接管的高价值场景。这些片段在全部车队数据中占比很小,却直接影响模型的安全性和长尾场景覆盖能力。
真正困难的部分通常不是采集数据,而是从海量行车记录中找到正确的数据。主要瓶颈及对应方案包括:
异常片段稀少且上下文分散。车辆持续产生多路相机、点云、定位、车辆状态和模型输出,一次异常可能只存在于几秒钟的片段中,并发生在不同车型、道路、天气和传感器版本下。Doris 可先按时间、车型、道路、天气和模型版本等业务条件缩小搜索范围。
已有标签难以覆盖全部语义。仅按时间、车辆或标签查询,容易漏掉语义相似但尚未标注的片段。Lance 保存 Episode 元数据、Embedding 和向量索引,Doris 复用索引召回相似场景。
相似结果还不是工程结论。只做向量相似度检索,可能召回业务上下文不相关的结果,也无法直接判断问题频次、模型版本回归和样本价值。候选结果进入 Doris 后,可继续执行分布式统计与版本对比,筛选值得进入标注、训练和评测的 Episode。
3.2 一条可落地的难例挖掘链路
设想团队希望定位“与某次异形障碍物急刹事件视觉语义相似、且发生在城市道路上的片段”,并判断问题是否集中于特定感知模型版本:
Lance Dataset 保存
episode_id、时间、道路与天气标签、车型、模型版本、接管/急刹结果、图像或片段 Embedding,以及原始媒体定位信息;Doris 将时间范围、城市道路、车型和模型版本等条件下推,在向量候选生成前收窄搜索空间;
Doris 复用已有 Lance 向量索引并并行搜索;索引未覆盖的 Fragment 自动以 Flat Search 补齐;
各并行任务返回局部候选,Doris 合并为全局 Top-K;
SQL 按模型版本、天气和道路类型聚合接管率、急刹率与样本量,形成难例分布;
候选
episode_id进入人工复核、标注、训练集或回归评测集,原始媒体由 Lance SDK 精确读取。

【图 2】智能驾驶难例挖掘:从车队数据到模型迭代
这条路径的关键不是把所有能力塞进一个存储格式,而是让“近似场景”不再脱离业务上下文。算法工程师得到的不只是一页相似图片,还能回答:相似问题出现在哪些版本、是否正在回归、覆盖了多少车辆和道路条件,以及哪些 Episode 最值得进入下一轮训练。
3.3 用一条 SQL 找到相似场景
假设 Lance Dataset 已由上游工具创建 scene_embedding 索引,可通过 Doris 的 vector_search() 发起检索:
SELECT
episode_id,
event_time,
road_type,
weather,
model_version,
intervention,
_distance
FROM vector_search(
"table" = "lance_ai.autodrive.scene_episodes",
"column" = "scene_embedding",
"query_vector" = "[0.12, -0.08, 0.31, ...]",
"top_k" = "200",
"metric" = "cosine",
"nprobes" = "20",
"refine_factor" = "10",
"filter" = "road_type = 'urban' AND event_time >= '2026-08-01'",
"use_index" = "true"
)
ORDER BY _distance ASC, episode_id;
这里的 filter 是检索前过滤:先限定正确的场景范围,再生成向量候选,通常比在 TVF 外部使用 WHERE 做检索后过滤更符合难例挖掘语义。_distance 越小表示越相似;显式增加唯一键作为第二排序字段,可让相同距离下的返回顺序稳定。
向量候选还可以继续进入标准 SQL 聚合。例如按模型版本统计相似场景中的接管分布:
WITH similar_scenes AS (
SELECT model_version, weather, intervention, _distance
FROM vector_search(
"table" = "lance_ai.autodrive.scene_episodes",
"column" = "scene_embedding",
"query_vector" = "[0.12, -0.08, 0.31, ...]",
"top_k" = "1000",
"metric" = "cosine",
"filter" = "road_type = 'urban'",
"use_index" = "true"
)
)
SELECT
model_version,
weather,
COUNT(*) AS scene_count,
SUM(CASE WHEN intervention THEN 1 ELSE 0 END) AS intervention_count
FROM similar_scenes
GROUP BY model_version, weather
ORDER BY intervention_count DESC;
四、具身智能:让每个 Episode 都可检索、可对比、可复盘
4.1 机器人数据的难点是跨频率对齐、随机访问和跨 Episode 分析
一个具身智能任务通常同时产生多种频率、不同形态的数据:机械臂状态和控制信号可能以百赫兹采集,多路相机以数十帧每秒记录环境变化,此外还有语言指令、逐帧标签、模型中间结果以及任务成功、失败和重试信息。
如果这些数据分别保存在视频文件、列式文件和 JSON 中,团队不仅需要维护跨文件的时间戳对齐和版本对应关系,还要为训练、回放与问题分析重复编写数据拼接逻辑。一次随机读取可能要先定位视频片段,再寻找对应的状态和动作记录;Schema 或特征发生变化时,不同数据副本也容易失去一致性。
训练框架关注的是如何高吞吐地读取一批样本,而研发分析关注的是如何在数百万个 Episode 中定位相似失败、比较不同策略和硬件版本,并判断问题属于感知、规划、控制还是执行环节。只有随机访问能力并不能完成这种跨 Episode 的聚合和归因,传统数仓式全表扫描也不适合承担全部多模态样本访问。
Lance 按 Episode 和时间轴组织状态、动作、特征、Embedding 与媒体定位信息,保留面向训练和复核的随机访问路径;Doris 则在其支持的字段上完成条件筛选、向量召回和跨 Episode 聚合。两者分工让机器人数据既能服务模型训练,也能被统一分析和复盘。
4.2 从失败任务定位到训练数据闭环
对于“机械臂抓取透明或反光物体失败”的问题,团队可以采用以下流程:
多路相机、关节状态、动作轨迹、指令、策略版本和任务结果按 Episode 进入 Lance;
上游模型生成视觉或轨迹 Embedding,并在 Lance 中建立向量索引;
Doris 先按机器人型号、任务类型、策略版本与
success = false做检索前过滤;向量检索找到与目标失败模式相似的画面或动作片段;
Doris 聚合失败原因、重试次数、任务耗时、硬件和策略版本,判断问题是感知、规划、控制还是硬件相关;
高价值 Episode 被送往复核、再标注和训练,修复后的模型再通过相同数据集做回归验证。

【图 3】具身智能 Episode 分析:从多频传感器到训练闭环
尤其适合 Agentic Data Workflow:Agent 可以先用 SQL 确定任务范围,再调用向量检索定位相似失败,最后生成分布统计和候选 Episode 清单。每一步都保留明确的筛选条件、SQL 和数据版本,比只让模型在文件目录或向量库中“盲搜”更容易解释和复核。
4.3 一个机器人失败模式检索示例
query_vector 由上游使用与 frame_embedding 相同的 Embedding 模型生成。例如,可以将一张参考图像、视频中的代表帧或一段动作轨迹送入模型,得到浮点数组后再传给 vector_search()。查询向量的维度、数值类型和归一化方式必须与数据集中的向量列以及建索引时保持一致;示例中的 [-0.04, 0.27, 0.18, ...] 仅用于展示参数格式。
SELECT
episode_id,
robot_model,
policy_version,
task_type,
failure_reason,
retry_count,
_distance
FROM vector_search(
"table" = "lance_ai.robotics.task_episodes",
"column" = "frame_embedding",
"query_vector" = "[-0.04, 0.27, 0.18, ...]",
"top_k" = "300",
"metric" = "cosine",
"filter" = "task_type = 'pick' AND success = false",
"use_index" = "true"
)
ORDER BY _distance ASC, episode_id;
结果可以继续按 policy_version、robot_model 或 failure_reason 聚合,也可以返回 episode_id 和媒体定位字段,由应用侧使用 Lance SDK 打开相应视频帧、点云或其他 Blob 内容进行复核。
五、如何在 Apache Doris 中使用 Lance Catalog
5.1 连接对象存储上的 Lance Dataset
下面以 S3 兼容对象存储为例。生产环境应通过安全的凭证管理方式提供访问密钥,不要把真实密钥直接写入共享脚本。
CREATE CATALOG lance_ai PROPERTIES (
"type" = "lance",
"lance.catalog.type" = "filesystem",
"warehouse" = "s3://<bucket>/physical-ai",
"s3.endpoint" = "https://<object-storage-endpoint>",
"s3.region" = "<region>",
"s3.access_key" = "<access-key>",
"s3.secret_key" = "<secret-key>"
);
Doris 也支持本地文件系统、OSS,以及采用 Bearer Token、API Key 或自定义 Header 认证的 Lance REST Catalog。Filesystem Catalog 按目录映射 Namespace:仓库根目录下的一层目录对应 Doris Database,.lance 目录对应 Table。
5.2 发现数据集、Schema 与已有索引
SHOW DATABASES FROM lance_ai;
SHOW TABLES FROM lance_ai.autodrive;
DESC lance_ai.autodrive.scene_episodes;
SHOW INDEX FROM lance_ai.autodrive.scene_episodes;
SHOW INDEX 用于查看已由 Lance 生态工具创建的索引。
5.3 使用 Catalog 执行向量查询
SELECT episode_id, event_time, model_version, _distance
FROM vector_search(
"table" = "lance_ai.autodrive.scene_episodes",
"column" = "scene_embedding",
"query_vector" = "[0.12, -0.08, 0.31, ...]",
"top_k" = "200",
"metric" = "cosine",
"filter" = "road_type = 'urban'",
"use_index" = "true"
)
ORDER BY _distance ASC, episode_id;
这样,从创建 Catalog、发现数据集到向量检索都在同一个 Catalog 命名空间中完成。filter 在候选生成前限定城市道路场景,_distance 返回相似度距离;查询向量的维度和距离度量需要与上游生成 Embedding、创建 Lance 索引时保持一致。
前过滤与后过滤的区别在于条件参与候选生成的时机。
把条件写在
vector_search()的filter参数中属于前过滤:Lance 先筛选满足条件的数据,再在这个子集内执行向量召回,因此top_k表示过滤后数据中的 Top-K,适合道路类型、时间范围、车型、租户或数据权限等必须约束检索空间的条件。把条件写在 TVF 外层的
WHERE中属于后过滤:向量检索先产生候选,Doris 再对候选执行过滤;它适合 Lance 暂时无法下推的表达式,或者“先按语义召回、再做业务筛选”的场景,但最终结果可能少于top_k,系统不会自动扩大召回范围来补足数量。
实际查询可以组合使用两者:将决定检索范围的强约束放入 filter,将复杂计算或剩余条件放在外层 WHERE,并通过 EXPLAIN 确认哪些条件已经下推。
5.4 用 EXPLAIN 确认谓词下推和索引命中
在正式执行前,可对同一条 vector_search() 查询使用 EXPLAIN。执行计划中的 lancePushdownPredicate 表示检索前条件已下推,lanceSearchIndexSegments 表示已规划 Lance 索引段;未被索引覆盖的新 Fragment 会使用 Flat Search 补齐,以保证当前快照内数据完整。
EXPLAIN
SELECT episode_id, _distance
FROM vector_search(
"table" = "lance_ai.autodrive.scene_episodes",
"column" = "scene_embedding",
"query_vector" = "[0.12, -0.08, 0.31, ...]",
"top_k" = "200",
"metric" = "cosine",
"filter" = "road_type = 'urban'",
"use_index" = "true"
)
ORDER BY _distance ASC, episode_id;
5.5 不创建 Catalog 时,使用 TVF 临时读取
如果只需临时分析一个明确的 Lance Dataset,而不希望将它纳入 Catalog 管理,可以直接使用 S3 TVF。TVF 适合按路径读取和标量分析;需要复用 Catalog 中的 Dataset、Schema 与向量索引时,仍应优先使用前述 Lance Catalog 和 vector_search()。
SELECT episode_id, event_time, model_version
FROM s3(
"uri" = "s3://<bucket>/physical-ai/autodrive/scene_episodes.lance",
"s3.endpoint" = "https://<object-storage-endpoint>",
"s3.region" = "<region>",
"s3.access_key" = "<access-key>",
"s3.secret_key" = "<secret-key>",
"format" = "lance"
)
WHERE event_time >= '2026-08-01';
六、结语:把 AI 数据从“可存储”推进到“可决策”
智能驾驶与具身智能不会缺少数据,真正稀缺的是能够解释模型问题、覆盖长尾场景并推动下一轮迭代的高价值 Episode。
Apache Doris + Lance 的意义,不是再造一个封闭的数据平台,而是在开放格式上建立一条从多模态资产到业务决策的短路径:Lance 让 AI 数据可组织、可索引、可随机访问;Doris 让这些数据可筛选、可检索、可聚合、可被人和 Agent 用统一 SQL 理解。
当“找到相似场景”可以自然地继续回答“影响了哪个版本、发生了多少次、是否形成回归、应该进入哪套训练集”,多模态数据才真正进入了模型迭代和业务决策的闭环。
目前,Iceberg、Paimon、Lance 等多模湖仓能力已合入 Doris 4.2 发版分支,将随 4.2 版本于 9 月底正式发布。后续,我们将围绕性能、稳定性和易用性持续完善 Doris + Lance,重点包括:
针对不同数据规模、向量维度、Top-K、过滤选择率、索引覆盖率、并发度以及冷/热缓存建立可复现 Benchmark;
同时衡量 P50/P95/P99 延迟、吞吐、Recall、扫描字节、对象存储请求、网络流量、CPU 峰值和内存峰值;
持续优化 Split 均衡、大 Top-K 合并、高维向量、宽结果列回表、对象存储读取与缓存路径;
针对
nprobes、refine_factor、ef、use_index等参数提供场景化建议,并形成容量规划与故障诊断手册;完善 Lance 表管理能力;
支持数据导出为 Lance 文件。
对于正在评估 Iceberg、Paimon、Lance 等开放数据格式,或有实时湖仓、多模数据分析等实际需求的用户,可以添加 Doris 小助手(ApacheDoris_Official)了解。