快手：从分散存储到统一分析，Apache Doris 在万亿规模广告场景的应用
导读：面对万亿级广告数据存量、日均 3 亿行增量及数千个复杂查询模板的挑战，快手广告数据平台如何突破性能瓶颈、实现架构统一与体验跃升？本文系统介绍了快手广告团队从 ClickHouse on ES 混合架构，全面迁移至 Apache Doris 的统一分析实践，最终实现查询性能提升 20～90%，写入吞吐提升 3 倍，存储效率提升 60%。本文整理自快手高级计算引擎研发工程师 周思闽 在 Doris Summit 2025 中的演讲内容，并以演讲者第一视角进行叙述。快手是国内日活过亿的短视频平台，其广告投放平台是商业化外部广告主与快手电商商家进行广告投放的主要阵地，支持客户在平台上进行广告物料搭建、物料管理、策略变更、数据查看等操作，这对底层数据系统的存储、计算与查询性能提出了极高要求。要支撑如此大规模的广告投放与实时分析，底层数据架构面临巨大挑战。当前，快手的广告数据包括：由投放系统产生的物料数据以及用于数据分析的效果数据，这些数据呈现出三个显著特征：数据存量巨大：广告物料累计已达千亿级别，且随业务发展正向万亿规模迈进，存储体量位居公司前列，对架构扩展性提出极高要求。数据增长迅猛：仅 2025 年第一季度，日均新增广告物料数据同比激增 3.5 倍，要求底层引擎具备强大的实时写入与弹性扩展能力。数据模型复杂：整个数据体系涵盖约 700 个核心字段，涉及物料、投放、用户、效果等多个维度；同时，为应对多样化分析场景，沉淀的查询模板已超 4000 个，对查询引擎的兼容性与性能均是严峻考验。架构演进：从分散存储到统一分析01 早期架构及挑战早期存储架构中，物料数据由 MySQL、Elasticsearch 协同存储；效果数据主要存储与 Clickhouse 中。数据分析时，将分散在 MySQL、Elasticsearch 中的物料数据与 ClickHouse 中的效果数据进行高效关联查询，从而为广告主提供完整、及时的投放效果洞察。在如上所说的 ClickHouse on ES 架构中，用户提交的查询通常包含 Elasticsearch 外表（a）与 ClickHouse 内表（b）。ClickHouse 会解析查询中外表部分，将其转换为 Elasticsearch 查询语句，通过 HTTP 请求获取数据并封装为 Block，最后在引擎内部完成与内表的关联计算。然而，随着 Elasticsearch 中数据量持续增长，该架构逐渐暴露诸多问题：查询性能恶化：慢查询率上升至 35%，平均查询耗时达到 1.4 秒；存储瓶颈：Elasticsearch 单分片难以支撑 10 亿级以上数据量，扩容与数据重分布成本高；运维复杂度高：数据链路依赖组件多，运维与监控成本显著上升；问题定位困难：缺少 ClickHouse 与 Elasticsearch 之间的全链路可观测手段，出现查询延迟、数据不一致等问题时，需跨系统排查，耗时较长。02 选型目标及调研基于上述问题及挑战，我们为新架构设定了明确目标：慢查询率低于 5%；运维排查耗时降低至分钟级；支持单表万亿级别数据存储；保障数据实时性，延迟低于 5 分钟。基于以上目标，我们对 Apache Doris、ClickHouse、Elasticsearch 等主流 OLAP 引擎进行了全面的调研与性能压测。测试涵盖了写入吞吐、查询延迟、存储压缩率、全文检索性能等关键维度。在这过程中，ClickHouse 首先被排除，因其不支持唯一键模型，而广告物料数据存在大量更新场景，要求引擎具备主键更新能力。因此，重点在 Elasticsearch 与 Apache Doris 之间进行对比。综合测试结果，Apache Doris 在写入性能、查询效率、存储成本及运维复杂度等方面均表现优异，不仅能够满足既定架构目标，还在多个场景下显著优于 Elasticsearch。因此，我们最终选定 Apache Doris 作为下一代广告数据分析引擎。03 基于 Apache Doris 的统一分析引擎在实际应用中，我们引入 Apache Doris（计算引擎） 替换了原先架构中的 Elasticsearch、ClickHouse，设计了统一分析引擎 Bleem。通过在外部表模块中引入数据缓存层与元数据服务层，有效提升了跨源查询效率，使数据湖外表的查询性能接近内表水平，实现了关键的性能突破。具体来看，Bleem 架构自下而上分为 5 层：存储层：数据湖中的 Hive/Hudi 数据存储于 HDFS；存算分离模式下的内表数据存放于对象存储 BlobStore；存算一体模式下的内表数据则存储于本地磁盘。缓存层：将 Hive/Hudi 外部表数据缓存至 Alluxio，保障 I/O 稳定性，提升数据读取效率。计算层：Apache Doris 为核心引擎。不同项目组对应不同的 Doris 集群，以实现计算资源物理隔离，用户可按需申请计算资源。依托于 Doris 湖仓查询能力，可直接对 Doris 内表与外部 Hive/Hudi 数据查询。同时，Doris 也支持存算一体与存算分离两种部署方式，可根据实际需求灵活选择。服务层：元数据缓存服务实时监听 Hive 元数据变更，并同步至缓存中，以提升湖仓外部表的查询效率。接入层：将 OneSQL 作为统一查询接入网关，提供集群路由、查询改写、物化改写、查询鉴权、限流与阻断等功能。依托 Doris 强大的 OLAP 计算与湖仓一体能力，将此前分散的数据湖分析、实时 OLAP 查询、在线报表及全文检索等多种场景，统一整合至同一套引擎架构中，实现了技术栈的收敛与提效。该架构在实际落地中已带来显著收益：性能大幅提升：慢查询率低于 5%，整体查询性能提升了 20%～90%；存储扩展高效：支持万亿级别数据存储，水平扩容效率较 Elasticsearch 提升 10 倍以上；运维大幅简化：一套引擎覆盖全部查询场景，系统依赖组件少，运维复杂度显著降低；可观测性全面加强：Doris 支持全链路追踪与全面监控，平均问题排查时间降低 80%。迁移实践及调优经验整个迁移过程分为三个阶段，稳步推进以确保业务平稳过渡：第一阶段（试点验证）：选取关键词推广场景进行试点，跑通全量与增量数据导入流程，搭建双链路并行验证数据一致性与查询正确性。第二阶段（主体迁移）：迁移原 ClickHouse on ES 查询链路，将 Elasticsearch 中全量物料数据导入 Doris，完成业务切换后下线 Elasticsearch 集群。第三阶段（收尾统一）：迁移剩余纯 ClickHouse 场景，将无需关联 Elasticsearch 的查询任务及其数据全部迁移至 Doris，完成整体架构统一。在架构升级及迁移过程中，我们收获了许多实践及优化经验，在此逐一分享。01 解决极端场景下数据一致性问题在数据导入层面，我们基于 SeaTunnel 实现流式数据同步，该方式支持批处理场景下的 Overwrite 语义，所有导入均采用两阶段提交机制，以确保数据同步的最终一致性。而在基于 SeaTunnel 和 Spark 的数据同步过程中，我们遇到了极端场景下的数据重复问题。主要有两种情况：Spark 推测执行时，两个 Task 同时写入同一份数据并均完成 Doris 两阶段提交，尽管 Driver 只认定一个 Task 成功，但数据已重复。Spark Task 完成 Doris 提交后，在向 Driver 汇报前因抢占或异常退出，Driver 重启 Task 并重新写入数据。为解决该问题，我们在 Doris 的两阶段事务提交环节引入了 ZooKeeper 分布式锁机制，通过记录并校验事务状态来保证批同步的一致性。具体流程如下：准备提交阶段，先获取 ZooKeeper 临时锁，确保同一时间只有一个事务进入提交流程；获取锁后，将 Prepare 状态写入 ZooKeeper 临时节点，并记录当前事务 ID；查询上一个事务的状态：若不存在，直接提交当前事务；若上一事务处于 Prepare 状态，则先回滚上一事务，再提交当前事务；若上一事务已 Commit，则直接回滚当前事务；最终将 Commit 状态写入 ZooKeeper 持久节点，完成本次提交。02 Stream Load 机制优化为应对高并发数据导入，我们对 Apache Doris 的 Stream Load 机制进行了调优。通过合理配置任务优先级与合并（Compaction）参数，显著提升了写入吞吐与稳定性。Doris 内部通过 Load Channel 进行任务调度，以区分高优与普通优先级通道。调优的核心在于合理配置相关参数，例如当 Stream Load 任务指定的 timeout 时间小于 300 秒时，系统会将其判定为高优任务并分配至高优通道。参数优化如下：load_task_high_priority_threshold_second=300 compaction_task_num_per_fast_disk=16 max_base_compaction_threads=8 max_cumu_compaction_threads=803 差异化的建表策略OLAP 引擎的查询性能很大程度上取决于表结构设计。因此，我们针对不同业务场景制定了差异化的建表策略：物料表（高频更新与大规模检索）：该表数据量极大且需支持实时更新。业务查询主要基于 account_id 进行过滤，而非原 MySQL 的自增 ID。为充分发挥 Doris 前缀索引与排序键的优势，在保证业务逻辑等价的前提下，我们将 account_id 与 id 组合为联合主键，并将account_id 设为首个排序键及分桶字段，大幅提升查询过滤效率。同时配置倒排索引以支持多维检索，并选用 ZSTD 压缩算法平衡存储与 IO 性能。-- 建表语句参考 CREATE TABLE ad_core_winfo (account_id BIGINT NOT NULL, id BIGINT NOT NULL, word STRING, INDEX idx_word (`word`) USING INVERTED...) UNIQUE KEY(account_id,id) DISTRIBUTED BY HASH(account_id) BUCKETS 1000;效果表（多维聚合分析）： 相较于物料表，效果表侧重于数仓指标的累加与聚合。因此，我们直接采用聚合模型，并按照“天”或“小时”粒度设置分区。-- 建表语句参考 CREATE TABLE ad_dsp_report (__time DATETIME, account_id BIGINT, ... `ad_dsp_cost` BIGINT SUM, ...) AGG KEY(__time,account_id,...) AUTO PARTITION BY RANGE(date_trunc(`__time`,'hour'))() DISTRIBUTED BY HASH(account_id) BUCKETS 2;04 大账户数据倾斜治理在数据压测中，我们发现不同 Account ID 对应的数据量差异极大，小至个位数、大至百万级别，导致 BE 节点 CPU 负载严重不均。通过 SHOW DATA SKEW 命令进一步确认，Tablet 存储分布明显倾斜：大 Tablet 占用空间达 3–4 GB，小 Tablet 仅 100-200 MB，且大账户查询延迟较高。为此，我们实施了以下两点优化：A：按账户范围进行分区经分析，Account ID 为 5–8 位数字，且未来不会超过 10 位。因此使用 FROM_UNIXTIME 函数将 Account ID 转换为 Datetime 类型，按月对历史数据进行分区，共划分出 33 个历史分区。每个分区可容纳 2,592,000 个 Account ID，后续每新增约 200 多万个 Account ID 才会新增一个月份分区。同时，针对历史分区，根据数据存量进行手动分桶，新分区则默认设置为 256 个分桶。该方案通过分区裁剪有效过滤了大量无关数据，同时为未来数据膨胀预留了扩展空间（物料表日均增量约 3 亿），显著降低分区增长对查询性能的影响。B：对 Account ID 进行二次哈希为缓解单个 Account ID 数据量差异过大导致的分布不均，我们选取与 Account ID 无关的 ID 字段，通过 ID MOD 7 计算得到一个取值在 0～6 之间的 mod 字段。将原本仅基于 account_id 的哈希分桶键调整为 (account_id, mod) 联合键，从而将同一 Account ID 的数据分散到 7 个 BE 节点上。优化后，各 Tablet 大小基本均衡稳定在 1GB 左右，数据存储与查询负载得以在多个 BE 间均匀分布，有效解决了 此前 CPU 负载不均的问题。05 万级分区下的查询优化当分区数量达到万级别时，简单点查 SQL 的耗时达到 250 毫秒，远超 100 毫秒的预期。通过分析，耗时主要集中在 Plan 阶段，原因是 Doris（2.1 版本）在分区裁剪时，会遍历所有分区进行匹配，万级分区的顺序遍历开销巨大。为此，我们将顺序遍历改为二分查找：对万级分区先进行排序，再利用二分查找快速定位目标分区，将时间复杂度从 O(n) 降至 O(log n)。优化后，该查询耗时从 250 毫秒降至 12 毫秒，性能提升超过 20 倍。目前，二分查找已在 Doris 3.1 版本中实现。06 并发调优在查询优化过程中，我们发现：多数查询经过条件过滤后，实际命中的数据量并不大，即便在大账户场景下，命中数据量也仅在百万级别。然而，Profile 显示这类查询的 Total Instance 数高达 800 个，其默认并发数为 32，存在明显的过度并发。为此，我们调整以下参数降低并发开销：set global parallel_exchange_instance_num=5; set global parallel_pipeline_task_num=2;调整后，同一查询的 Total Instance 数量降至 17 个，查询耗时也显著缩短。这说明在小数据量点查场景下，适当降低并发可有效减少 RPC 开销，从而降低延迟（220ms 降至 147ms）。同时，这一优化也提升了系统的整体 QPS 承载能力。收益及规划经过上述架构迁移与深度优化，我们在三个核心维度取得了显著收益：查询性能大幅提升：关键词推广页平均查询延迟下降 64%，创意推广页延迟下降超过 90%，整体查询体验实现跨越式提升。写入能力显著增强：单节点写入承载能力提升 3 倍以上，单表实时导入峰值突破 300 万行/秒。存储效率优化明显：通过分区策略与 ZSTD 压缩算法，存储效率较 Elasticsearch 提升约 60%，并可轻松支撑万亿级数据存储。未来，我们将深度探索 Apache Doris ，重点围绕两方面展开：增强全文检索与分词能力：引入社区在 Doris 4.0 版本中推出的 BM25 打分功能，以及 IK 分词器等更多分词组件，实现按业务场景灵活选用最优分词方案。增强向量索引：基于 Doris 4.0 版本，在内表和数据湖外表场景下对向量检索的性能和边界能力做验证与优化。本文完。您还可以阅读来自快手另一篇实践案以及中通快递、小米集团、顺丰科技用户故事来了解湖仓分析。
上市大模型企业数据基础设施的选择：MiniMax 基于阿里云 SelectDB 版，打造全球统一AI可观测中台
MiniMax 全球领先的通用人工智能科技公司。旗下主要有 MiniMax M2.1、Hailuo 2.3、Speech 2.6 和 Music 2.0 等大模型，MiniMax Agent、海螺 AI、星野、Talkie 等产品，以及为企业客户与开发者提供 API 服务的 MiniMax 开放平台。截至目前，MiniMax 已有超过 200 个国家及地区的逾 2.12 亿名个人用户以及超过 100 个国家的企业客户。在技术层面，MiniMax 坚持文本、视频、语音等全模态模型自主研发。目前，其全模态模型已进入国际第一梯队，被业内称为“全球唯四实现这一水平的企业之一”。在推理能力和效率方面，MiniMax 近年来的模型迭代节奏明显加快，在多项国际评测榜单中进入全球前列。相关模型以较低算力成本实现接近国际顶尖闭源模型的性能表现，也在海外开发者社区中获得关注。MiniMax 通过开放平台赋能多个行业，将领先的模型能力以 API 方式提供给企业和开发者。随着模型调用量的指数级增长，训练与推理产生的运行日志数据量也急剧膨胀。 这些日志对于 AI 应用的运行监控、性能优化与问题排查至关重要，因此，选择一款能够支撑高吞吐、易查询、低成本的日志存储与检索引擎，成为保障业务稳定高效运行的关键 。面对海量、实时且不断增长的日志数据处理需求，MiniMax 经过深度评估，最终选择阿里云数据库 SelectDB 版作为其全新可观测性数据平台的核心基座。阿里云数据库 SelectDB 版凭借其更低的成本、更高的查询性能以及更灵活的查询方式在众多产品中脱颖而出。其关键特性精准匹配了现代 AI 业务的严苛要求：云原生存算分离架构：基于对象存储 OSS 的存储层与弹性计算层解耦，支持独立、无损的弹性伸缩，为应对日志洪峰提供了近乎无限的扩展能力。多集群硬隔离与数据共享：支持云原生多集群硬隔离能力，用户可以将单个实例的计算资源划分为多个逻辑集群，不同集群之间的分配独立的计算资源，实现了不同集群的严格物理资源隔离和数据共享。智能缓存加速：通过单副本本地读写缓存、智能数据淘汰策略、高效列式存储格式和先进压缩算法，显著提升了海量数据的读写效率。阿里云数据库 SelectDB 植根于开源 Apache Doris 的坚实基础，深度融合云随需而用的特性，依托阿里云基础设施，构建起云原生存算分离的全新架构，面向企业海量数据的实时分析需求，提供极速实时、湖仓融合统一、简单易用的云上数仓服务。基于阿里云 SelectDB 版，MiniMax 构建了覆盖国内及海外业务的统一日志可观测中台。 以 SelectDB 独立负责所有日志的存储与查询分析，实现了 “一个平台，全球覆盖” 。这彻底终结了以往为不同业务集群分散部署、独立运维多套系统的复杂局面，在架构上实现了极大的简化。阿里云数据库 SelectDB 在 MiniMax 的成功实践足以说明：SelectDB 能够很好地满足 AI 时代海量数据实时处理与分析的需求。不仅为 MiniMax 自身业务的高效运营提供了坚实保障，也为广大面临类似日志处理挑战的 AI 大模型企业，提供了一个高性能、低成本的可靠技术解决方案。不止于此， 面对大模型与多模态 AI 的快速发展，SelectDB 已从被动存储分析向主动智能分析演进。目前，SelectDB 已具备 AI 原生支持能力，深度融合向量索引、文本搜索与结构化分析能力，实现高效的混合检索，显著提升结果相关性、实时性与准确性。更进一步，SelectDB 内置 AI 函数（如语义理解、特征提取）并支持基于 MCP 的 Agent 分析接口，可直接升级为企业的 “AI 分析中枢” ，为业务智能决策与创新提供稳定、高效的数据底座。
构建 AI 数据基座：思必驰基于 Apache Doris 的海量多模态数据集管理实践
导读：面对海量多模态数据管理困境，思必驰通过构建以 Apache Doris 为核心的数据集平台，实现了数据从“散、乱、滞”到“统、明、畅”的转变。在关键场景中，存储占用下降 80%、查询 QPS 提升至 3w，不仅实现可量化的效率提升和成本优化，更系统化地提升了 AI 研发效率与模型质量。本文整理自 思必驰数据中台架构师魏凯君在 Doris Summit 2025 中的演讲内容，并以演讲者第一视角进行叙述。思必驰作为专注于对话式人工智能的平台型企业，围绕“云+芯”战略布局，致力于提供软硬件结合的全链路 AI 产品与服务。在长期服务智能车载、家居等终端场景中，我们积累了海量的多模态训练语料（包含音频、文本及人工标注）。早期的数据管理方式逐渐成为 AI 研发的瓶颈。各业务团队的标注数据分散在不同的存储系统中，依赖人工进行维护和同步。随着数据规模快速增长至 PB 级别，传统方式在三个方面面临严峻挑战：数据一致性问题：同一份数据在不同团队中存在多个副本，且更新不同步，影响模型训练的一致性。协同效率低下：算法工程师难以快速查找、复用跨团队的数据资产，重复标注与数据准备浪费了大量时间。版本追溯困难：模型迭代时，无法精准关联训练所使用的数据版本，导致问题复现与效果归因困难。这些问题使得数据资产化与高效协同成为制约 AI 研发规模化的关键。为此，我们决定构建一个统一的数据集管理平台，目标是将原始数据标准化、资产化，打造一个支持高效调用、可靠追溯、安全共享的“AI 数据基座”。为何是 Apache Doris？思必驰与 Apache Doris 的合作始于早期技术实践。在 Doris 0.12 版本时期，我们率先将其应用于内部实时数仓场景，并随业务发展，逐步建立起面向外部服务的 Doris 集群，支撑了包括实时看板、用户画像与自助分析在内的多项数据能力。此外，Doris 在海量业务日志场景（容器日志）中也发挥了关键作用，替代了原有的 Elasticsearch，并基于 Doris 自建日志查询平台，服务智能座舱语音业务。在同等硬件资源下，日志写入性能从原来的 100w/s 提升至 300w/s，存储成本也降低了 50% 以上。基于 Doris 在性能、成本、稳定性方面的综合优势，在构建数据集平台时，它自然成为数据底座的首选。我们的新场景对数据库提出了更高要求：海量数据去重与高效查询：需处理 10 亿级样本的快速去重与复杂筛选。完善的版本管理：需支持数据集的版本化存储、快速切换与对比。支持向量检索能力：为后续的相似样本检索、特征比对提供支持。高性价比存储：需利用高效压缩与冷热分离，降低 PB 级数据的存储成本。综合评估，Apache Doris 在满足上述核心需求的同时，其简洁的架构、易用的运维以及活跃的社区，使其成为最优方案。面向 AI 大规模训练的数据基座我们采用类 MLOps 理念，设计了贯穿数据-模型-应用的标准化流水线。数据预处理：原始的多模态数据（语音、文本等）通过采集、回流进入系统，经由专业的标注平台进行加工，再进入 AI 数据前台进行清洗与特征提取。数据集管理系统：经过预处理的数据，汇入 基于 Apache Doris 构建的数据集管理系统（即本文核心） 。该系统是整个 AI 中台的关键，负责数据的版本化存储、管理与发布，为模型训练与测试提供数据支撑。模型训练及管理：测试数据集进入模型训练系统进行训练，生成的模型经模型管理平台统一管理，最终部署上线，服务于业务应用。由上图可知，数据集管理系统被囊括在 AI 中台这一架构中。纵观整个 AI 中台，主要包括三个部分：数据管理系统：基于 Apache Doris 和 Elasticsearch 构建，提供页面、客户端和相应的 SDK；AI 平台：基于推理与训练框架，以及资源管理与任务调度框架构建；同样提供页面、客户端和 SDK。底层基础设施：涵盖计算层、分布式存储体系及优化后的网络层。为满足不同业务场景需求，数据集管理 系统设计了单中心和多中心两种部署架构：单中心：面向核心研发场景，数据访问统一指向本中心的 Apache Doris、Elasticsearch、Kafka 及相关文件系统，保证最强的一致性与性能。多中心：面向跨地域或异构计算资源场景， 采用分布式设计。主中心的数据层使用 Apache Doris，各分中心采用独立的分布式文件系统，这些存储之间可以实现数据的相互同步。针对各个中心的训练任务，系统能够读取这些分布式文件存储中的数据进行训练。数据版本毫秒级切换，存储占用下降 80%过去，我们依靠人工在文件系统中维护数据集目录，随着版本激增，混乱与错误难以避免。新平台需要实现类似代码库的版本管理能力（对比、切换、回滚）。为此，我们利用 Doris 的特性进行改进：列式存储：将标注信息等结构化数据从文本文件迁移至 Doris 表，利用列式存储的高压缩特性，存储空间占用降低 80%以上。分区表实现版本化：以数据集版本作为分区键。最新活跃版本存放在 SSD（热存储），历史版本自动迁移至 HDD（冷存储），SSD 使用率降低 30%以上。表结构设计：核心围绕数据集表，关联文件表与标注表。通过分区机制，实现了毫秒级的历史版本数据检索与切换。精准溯源检索，查询 QPS 提升至 3W为解决模型训练后与原始数据脱节这一核心痛点，数据集平台内置了样本溯源能力。传统的流程在完成特征提取后，往往丢失了原始数据的属性与标注信息，导致两大问题：模型无法关联其“数据血缘”，以及不同模型版本间难以进行有效的对比调优。为此，我们确立了样本 ID 全局唯一的核心要求，以此支撑精准的溯源与检索。在样本检索实现初期，团队采用 Apache Doris 的 IN 查询方式支撑相关能力，而面对瞬时并发的规模点查请求时，会有明显资源与性能开销，部分节点峰值可达 80%。为此，团队基于 Apache Doris 的相关能力进行优化，主要采用两类改进：首先，根据“高频点查”这一核心特征，切换至行式存储并优化 I/O 路径，使单次查询更快。其次，通过全面启用预处理语句，将查询计划固定下来，避免了大量的重复计算开销。优化后，在现有配置下，查询 QPS 提升至 3 万/秒；同时在高频点查询期间，CPU 占用由原先约 80% 降至约 10%，并持续稳定。平台收益：可量化的效率提升与成本优化在平台落地后，形成了可量化的建设成效：数据集规模超过 1 万个，数据总量超过 500TB，样本数量超过 10 亿，平台使用人数超过 200 人。通过新旧架构对比，新平台在三个维度带来了显著收益：成本大幅优化：通过消除数据冗余拷贝，存储成本降低 20% 以上，网络成本节约超 3 倍。效率全面提升：数据查询效率提升超 3 倍，数据同步效率提升超 2 倍。研发显著提效：模型研发流程效率提升 20% 以上，且数据集使用得以全面规范。更重要的是形成了不可替代的隐性价值：统一了数据质量标准：公司内研发、测试、业务团队使用同一套数据和规范，从根本上保障了模型输入的一致性。增强了问题复现能力：任何模型结果均可精准追溯至对应的训练数据集与版本，使得问题调试、效果归因有据可依。实现了流程自动化闭环：结合自动标注系统，实现了从数据回流、清洗、标注到训练的数据闭环，极大提升了 Badcase 的定位与修复效率。未来规划基于当前的成功实践，未来我们将继续深化 Apache Doris 的应用，推动数据架构向更先进的方向演进：日志分析场景全面替换：已在 TPS 15 万量级场景完成验证，将加速推进用 Doris 替代 Elasticsearch，预计进一步降低日志处理总成本。拥抱 Doris 4.0 新特性：重点关注并计划升级至 Doris 4.0 版本，利用其向量检索能力，支持更复杂的相似性查询与 AI 原生应用。探索湖仓一体架构：打破数据孤岛，实现数据在数据湖（低成本存储）与数据仓库（高性能分析）间的自由流动与统一管理，支撑 SQL 查询、机器学习等多样化负载。推进存算分离落地：实现计算资源的按需弹性伸缩与负载隔离，并将冷数据沉降至对象存储，在提升资源利用率的同时，追求极致的存储成本效益。
引言：随着大模型和多模态 AI 的快速发展，向量已成为文本、图像、音视频等多元数据的通用语义表示。在这种背景下，检索增强生成（RAG）技术成为连接私有知识与大模型的核心桥梁，而高效的向量检索则是其关键支柱。与将向量检索视为独立外挂服务的方案不同，Apache Doris 4.0 选择将向量检索能力深度集成于其 MPP 分析型数据库内核。实现向量检索与 SQL 计算、实时分析和事务保障的无缝融合。本文旨在深入剖析 Doris 向量检索的系统级设计与工程实践，展示其如何在性能、易用性与规模扩展之间取得的平衡。1. ANN 索引核心设计Apache Doris 的向量索引基于 ANN（近似最近邻）算法实现，并非独立的外挂组件，而是深度集成于存储、执行与 SQL 引擎中的原生能力。在 4.x 版本中，其核心 ANN 索引能力主要包括以下几方面：多索引类型与距离度量支持：支持主流的 ANN 索引类型（HNSW、IVF）及常见距离度量（L2 距离、内积）。用户可根据业务在构建速度、内存占用与召回率上的要求灵活权衡。原生 SQL 集成：向量检索以原生 SQL 算子形式提供，支持直接定义向量列、通过 ORDER BY distance LIMIT K 进行相似度搜索，并能与过滤、聚合、JOIN 等算子自由组合，天然支持混合检索与分析。构建与查询解耦：采用异步索引构建机制，数据导入后即可查询，索引在后台构建并加载，避免导入阻塞，保障查询高峰期的稳定低延迟写入。向量压缩优化：在导入与构建阶段支持标量量化（SQ）、乘积量化（PQ）等压缩技术，显著降低存储与内存开销，提升高维大规模向量场景的资源效率。分布式并行执行：依托于分布式架构，Doris 向量索引天然支持数据分片与索引分布式存储；查询可在各 BE 节点并行执行；Top-K 结果在上层进行合并与裁剪。随着节点数量增加，系统能够在数据规模与吞吐能力上实现近线性扩展。2. Benchmark & AnalysisApache Doris 的目标并非追求单一指标的极限表现，而是在真实生产负载下，实现性能的均衡性、系统稳定性与架构可扩展性。本次测试将围绕这一目标展开，所用工具为 ZillizTech 开源的向量搜索 BenchMark：https://github.com/zilliztech/VectorDBBench。云服务商：阿里云CPU：Intel Xeon Platinum 8369B @ 2.70GHz (16 核)内存：64GB2.1 导入与构建性能测试结果表明，在 Performance768D1M 数据集上，Apache Doris 在保证同等索引质量的前提下，导入性能显著优于对比系统。尤为重要的是，其导入速度的提升并未以牺牲图结构质量为代价。Doris 在 QPS 达到 895 的同时，仍保持了 97% 以上的召回率，在性能三角的三个维度上取得了出色的平衡。2.2 查询性能即便单独考量查询性能，Apache Doris 同样处于业界第一梯队。在 Performance768D10M 数据规模上，当召回率要求高于 95% 时，Apache Doris 的 QPS 表现优于 OpenSearch 与 Qdrant。此结果为默认配置下的开箱性能，未针对 Segment 文件数量等进行专项调优。这里比较的是开箱性能测试，即不做 segment 文件数量的优化时的性能对比。Milvus 的 flat 版本以及 Cloud 版本会有更好的性能表现，但是其出品的 VectorDBBench 只提供了 SQ8 量化后的成绩。3. 核心设计与性能优化Apache Doris 采用 FE（协调节点）与 BE（计算节点）构成的分布式架构。BE 作为核心执行单元，承担查询计划执行与数据导入任务，负责几乎所有高负载计算与大规模数据吞吐，是系统高性能的基石。尤其在向量场景下，数据写入、索引构建与向量距离计算都属于典型的 CPU 与内存密集型工作。为充分发挥其性能、保障系统稳定运行，我们对 ANN 索引的写入、构建与查询路径进行了系统优化。3.1 写入与构建路径优化优化主要分为两类：功能优化与性能优化。在功能层面，依托 Doris 成熟的分布式集群管理与存储管理能力，引入 LightSchemaChange 实现轻量级的索引管理机制，这是目前专用向量数据库普遍不具备的能力。在性能层面，重点聚焦于索引构建流程的优化，以显著提升索引构建速度和整体吞吐能力。3.1.1 异步索引构建机制Apache Doris 针对 ANN 索引构建开销大的问题，提供了异步构建机制。用户可在数据导入后，选择业务低峰期触发索引构建；在查询高峰时，仅需将已建好的索引加载至内存即可快速检索，从而将密集的 CPU 消耗转移至成本更低的时段。在 FE 侧，CREATE INDEX 与 BUILD INDEX 通过 SchemaChangeHandler 编排：为每个分区创建影子索引与影子 Tablet（IndexState.SHADOW），并建立 origin→shadow 的 Tablet 映射与影子副本（副本初始态为 ALTER）。生成新的 schema version/hash，保障新旧版本隔离。通过 FE→BE 的 AgentTask（Thrift）分发构建任务到各 BE，BE 在 Tablet 层面完成索引数据构建。构建成功后，FE 原子性地将影子索引切换为正式索引，更新元数据并清理旧工件。该流程在保证线上业务可读写的同时，实现了索引构建的在线隔离与数据一致性。3.1.2 导入性能优化为在保障索引质量的前提下提升写入吞吐与稳定性，Doris 采用了 多层级分片、双层并行、SIMD 向量化计算 的组合方式进行优化。A. 多层级分片Apache Doris 将逻辑表在内核层拆分为多个 Tablet。每次数据导入会生成一个 Rowset，每个 Rowset 又包含若干 Segment，而 ANN 索引正是在 Segment 粒度上构建与使用的。这一设计将“全表数据量”与“索引超参数”解耦，用户只需根据单批次导入的数据规模来设定参数，无需因数据总量增加而反复重建索引。以单 BE 单分桶的典型场景为例，我们从实际经验中总结出如下参数可供参考：得益于 Apache Doris 的分片架构下，索引参数可稳定在合理的规模区间，不受全表数据总量增长的影响。换言之，索引超参数的设置只需基于单个 Tablet 单次导入的数据行数。即便集群规模扩大，也仅需根据机器与分桶数量相应调整批次大小（batch size）即可。以 HNSW 索引为例，在单 BE 集群中，针对每批导入 25 万、50 万、100 万行的典型规模，分别选择 max_degree≈100/120/150、ef_construction≈200/240/300、hnsw_ef_search≈50~200，即可在延迟可控的同时平衡召回与构建成本。经验上，召回率随 hnsw_ef_search 提高而改善，但查询延迟也会线性增加。max_degree 与 ef_construction 过小会导致图结构稀疏、查询不稳定；过大则会显著增加构建时间与内存占用。因此，建议结合业务对召回和延迟的要求，通过离线压测确定最佳参数组合。B. 双层并行构建集群层由多台 BE 并行处理导入批次；单机内再对同一批数据进行多线程距离计算和图结构更新。配合“内存攒批”（在内存中适度合并小批次），可避免过细分批导致的图结构稀疏与召回下滑，在固定超参数下获得更稳定的索引质量与构建速度。以 768 维、1,000 万条向量为例：分 10 批构建的召回率约可达 99%，若切成 100 批则可能降至约 95%。适度的内存攒批既不显著抬高内存峰值，又能提升图连通性和近邻覆盖，从而减少查询阶段的回表与重复计算。C. SIMD 加速向量距离计算是典型的 CPU 密集型计算。Doris 在 BE 侧采用 C++ 实现距离计算，引入 SIMD（单指令多数据）并行计算。可以更少的指令、更少的访存，更快完成把同样的距离，从而显著提升向量索引构建和重排阶段的吞吐能力。具体来讲：并行计算多个维度：利用 SSE / AVX / AVX-512 等指令集，同时加载和计算 8～16 个浮点数，而非逐维循环。减少内存访问：在计算前对向量数据进行批处理和转置，使数据在内存中连续排列，优化 CPU Cache 访问模式。合并计算步骤：使用 FMA（乘加融合）指令，把“乘法 + 加法”合并为一步，并通过水平求和快速聚合向量数据。高效处理边界情况：对维度不对齐的尾部数据，使用掩码指令统一处理，避免额外分支和判断。3.1.3 向量压缩技术以 HNSW 为代表的高性能索引数据结构通常将向量与图结构常驻内存。在 RAG 场景中，文本/图片/音频等模态向量维度约为 1,000，若每维使用 FLOAT32 存储，一百万行占用 4 GB，千万行则约 40 GB。考虑到索引结构的额外占用（约 1.3 倍），一千万行整体接近 52 GB。以 16C64GB 机器为例，单机索引上限约为千万级，需预留空间以避免 OOM，并保障查询和构建的并行开销。为了显著降低内存占用、扩展单机承载能力，向量压缩技术成为关键。Apache Doris 在此提供了两种主流的实现方案：标量量化与乘积量化。A. 标量量化（Scalar Quantization，SQ）标量量化通过用低精度类型替换高精度类型来压缩存储空间，Doris 支持 INT8 和 INT4 的标量量化，并在导入和构建阶段完成编码。如若将 FLOAT32（4 字节）替换为 INT8（1 字节）可节省约 75% 存储，进一步压缩为 INT4 则节省约 87.5%。如果压缩后数据的分布形态保持一致，召回率在可控延迟内接近未压缩效果。上图展示了在 128 维和 268 维向量上的测试结果。相比 FLAT（不编码，用完整 Float32 表示每个浮点数），SQ8 可实现接近 2.5 倍的压缩，而 SQ4 可实现接近 3.3 倍的压缩。值得说明的是，引入 SQ 不可避免的会带来额外的压缩计算开销（索引构建阶段），且标量量化更适用于各维度近似均匀分布的数据。如遇分布呈高斯或更复杂形态时，标量量化误差增大，则可采用乘积量化方式。B. 乘积量化（Product Quantization， PQ）RAG 等场景中，由 Transformer 编码器生成的向量，存在明显的语义结构、分布不均匀。乘积量化通过子空间划分 + 子空间学习型量化，能够更好地适配。PQ 将高维向量分割为多个子向量，并为每个子空间独立训练一个码本（例如通过 k-means 聚类学习质心）。这使得数据密集区域能用更精细的码本保持细节，从而在整体上用更短的码长维持原始的距离关系。查询时通过查表与累加来估算距离，大幅减少了计算与内存访问开销。我们在 128 维与 268 维上对比 SQ 与 PQ，参数统一设定为 pq_m = dim/2、pq_nbits = 8。从空间占用看，PQ（m=68/128， nbits=8）的内存占比与 SQ4 大致相当，可实现约 3× 压缩。除构建更快外，PQ 还可依赖查表加速解码，体现在更优的查询速度上。关于 PQ 的超参数，实际使用时建议结合数据分布进行针对性适配与调优。根据经验，将 pq_m 设为原始维度的一半，pq_nbits 设为 8，在多数场景下即可取得良好的效果，可作为初始调优的参考起点。综合来看，对于用户来说， SQ 和 PQ 该如何选择呢？从使用上来说，SQ 的优点是使用方式简单，只需要指定数据类型即可，而 PQ 的使用门槛更高，需要对其原理有较为深刻的理解才能在生产环境中发挥其优势。从性能及开销上来说，SQ 在解码阶段存在额外计算开销，且随维度增加开销更高；PQ 则能在压缩的同时保持接近原始向量的查询性能。从场景上来说，SQ 更适用于各维度近似均匀分布的数据。如遇分布呈高斯或更复杂形态时，标量量化误差增大，则可采用乘积量化方式。3.2 查询执行路径优化搜索场景对延迟极为敏感。在千万级数据量与高并发查询的场景下，通常需要将 P99 延迟控制在 200 ms 以内。这对 Doris 的优化器、执行引擎以及索引实现都提出了更高要求。Apache Doris 为此做了大量优化，这一章节对其中涉及到的部分能力做介绍。3.2.1 虚拟列机制Apache Doris 的向量索引采用外挂方式。外挂索引便于管理与异步构建，但也带来性能挑战：如何避免重复计算与多余 IO？ANN 索引在返回行号时，会同步计算出向量距离。执行引擎在 Scan 算子阶段可直接利用该结果进行筛选和排序，无需在读取数据后重新计算。这一过程通过 “虚拟列” 机制自动实现，最终以 Ann Index Only Scan 的形式运行，完全消除了因距离计算而产生的数据读取 I/O。未应用 Index Only Scan：应用 Index Only Scan 后：例如 SELECT l2_distance_approximate(embedding, [...]) AS dist FROM tbl ORDER BY dist LIMIT 100;，执行过程将不再触发数据文件 IO。该优化不仅适用于 TopK 检索，也支持 Range Search、复合检索（Range + TopK）以及与倒排索引结合的混合检索场景，实现了全路径的 Index Only Search。虚拟列机制并不局限于向量距离计算。对于正则抽取、复杂标量函数等 CPU 密集型表达式，若在同一查询中被多次引用，该机制也能复用中间结果，避免重复计算。以 ClickBench 数据集为例，以下查询统计从 Google 获得最多点击的 20 个网站：set experimental_enable_virtual_slot_for_cse=true; SELECT counterid, COUNT(*) AS hit_count, COUNT(DISTINCT userid) AS unique_users FROM hits WHERE ( UPPER(regexp_extract(referer, '^https?://([^/]+)', 1)) = 'GOOGLE.COM' OR UPPER(regexp_extract(referer, '^https?://([^/]+)', 1)) = 'GOOGLE.RU' OR UPPER(regexp_extract(referer, '^https?://([^/]+)', 1)) LIKE '%GOOGLE%' ) AND ( LENGTH(regexp_extract(referer, '^https?://([^/]+)', 1)) > 3 OR regexp_extract(referer, '^https?://([^/]+)', 1) != '' OR regexp_extract(referer, '^https?://([^/]+)', 1) IS NOT NULL ) AND eventdate = '2013-07-15' GROUP BY counterid HAVING hit_count > 100 ORDER BY hit_count DESC LIMIT 20;核心表达式 regexp_extract(referer, '^https?://([^/]+)', 1) 为 CPU 密集型且被多处复用。启用虚拟列优化（set experimental_enable_virtual_slot_for_cse=true;）后，端到端性能提升约 3 倍。3.2.2 前过滤与谓词下推在 ANN TopN 检索中，过滤谓词的应用时机是关键的设计权衡：前过滤：在 TopN 之前应用谓词，能阻止无效行进入候选；但需在候选集维护过程中实时剔除不符合条件的行。后过滤：先按相似度取出 TopN，再执行过滤，可能导致最终结果不足 N 条。虽然可通过扩大 N 来补偿，但会额外增加扫描与计算开销。Apache Doris 在 Scan 算子内通过 row bitmap 实现自然的前过滤语义。每个谓词执行后即时更新 row bitmap。当 TopN 下推到 Scan 时，向索引传递一个基于 row bitmap 的 IDSelector，仅保留满足条件的行作为候选，从源头上避免无效候选进入 TopN。为进一步提升效率，Doris 还会在扫描前借助分区、分桶、ZoneMap 等轻量元数据进行快速预过滤，并结合倒排索引进行精确的行号定位，多层次缩小候选集，能够显著提升查询性能与资源效率。3.2.3 全局执行优化在传统执行路径中，Doris 会对每条 SQL 执行完整优化流程（语法解析、语义分析、RBO、CBO）。这在通用 OLAP 场景必不可少，但在搜索等简单且高度重复的查询模式中会产生明显的额外开销。为此，Doris 进行了全局执行优化，充分发挥索引、过滤等性能。A. Prepare Statement：Doris 4.0 扩展了 Prepare Statement，使其不仅支持点查，也适用于包含向量检索在内的所有 SQL 类型。Prepare Statement 的原理是将 SQL 编译与执行分离，模板化检索复用计划缓存，Execute 阶段跳过优化器。查询计划按“标准化 SQL + schema 版本”构建指纹进行缓存，执行阶段校验 schema version，变化则自动失效并重建。对频繁且结构相同仅参数不同的检索，Prepare 能显著降低 FE 侧 CPU 占用与排队等待。B. Scan 并行度优化：为提升 ANN TopN 检索性能，Doris 重构了 Scan 并行策略。原策略基于行数划分任务，在高维向量场景下，单个 Segment 的实际行数常远低于划分阈值，导致多个 Segment 被分配至同一任务中串行扫描，制约性能。为此，Doris 改为严格按 Segment 创建 Scan Task，显著提升了索引检索阶段的并行度。由于 ANN TopN 搜索本身过滤率极高（仅返回 TopN 行），后续回表阶段即使串行执行，对整体吞吐与延迟的影响也微乎其微。以 SIFT 1M 数据集为例，开启 optimize_index_scan_parallelism=true 后，TopN 查询耗时从 230ms 降至 50ms，效果显著。此外，4.0 引入动态并行度调整：每轮调度前根据 Scan 线程池压力动态决定可提交的任务数；压力大则减并行、资源空闲则增并行，以在串行与高并发场景间兼顾资源利用率与调度开销。C. TopN 全局延迟物化：典型的 ANN TopN 查询可分为两个关键阶段：局部检索与全局归并。在局部检索阶段，Scan 算子通过索引获取每个数据分片（Segment）中的局部 TopN 近似距离；随后在全局归并阶段，由专门的排序节点对所有分片的局部结果进行合并，筛选出最终的全局 TopN。传统执行流程存在一个显著效率问题：若查询需要返回多列或包含大字段（如长文本），在第一阶段就会读取这些列的全部数据。这不仅会引发大量磁盘 I/O，而且绝大多数被读取的行会在第二阶段的排序竞争中被淘汰，造成计算与 I/O 资源的浪费。为此，Doris 引入了 “全局 TopN 延迟物化” 优化。该机制将非排序所需列的读取推迟到最终结果确定之后，大幅减少了不必要的 I/O。优化执行流程示例：以 SELECT id, l2_distance_approximate(embedding, [...]) AS dist FROM tbl ORDER BY dist LIMIT 100; 为例：局部轻量扫描：每个 Segment 利用 Ann Index Only Scan 结合虚拟列技术，仅计算出局部 Top 100 的距离值（dist）及其对应的行标识（rowid），不读取其他列。全局排序筛选：系统汇总所有 M 个 Segment 的中间结果（共 100 × M 条候选），对其进行全局排序，从而确定最终的 100 个目标 rowid。按需延迟物化：最终的 Materialize 算子根据上一步得到的 rowid，精准地到对应的存储位置读取所需列（例如 id）的数据。通过将完整数据的“物化”步骤推迟到最后，该优化确保了查询前期仅处理轻量的距离与行标识信息，彻底避免了在排序前读取非必要列所带来的 I/O 开销，从而显著提升了整体查询效率。4. 实战：使用 Apache Doris 搭建企业知识库企业级知识库是 RAG 的典型落地场景。因此，我们基于 LangChain + Apache Doris 搭建了一个以 Doris 官网文档为语料的最小可用知识库，用于验证 Doris 向量检索的端到端能力。完整示例代码见 GitHub。（1）环境准备LLM：用于对话与答案生成，这里使用 DeepSeek。先在官网注册并创建 API Key，妥善保存，后续用于调用 DeepSeek API。嵌入模型：用于生成检索向量，这里使用 Ollama + bge-m3:latest。bge-m3 是开源的通用检索向量模型，兼顾中英文检索效果，默认输出 1024 维向量，适合知识库检索场景。（2）建库与建表（方式一：SQL）CREATE DATABASE doris_rag_test_db; USE doris_rag_test_db; CREATE TABLE doris_rag_demo ( id int NULL, content text NULL, embedding array<float> NOT NULL, INDEX idx_embedding (embedding) USING ANN PROPERTIES("dim" = "1024", "ef_construction" = "40", "index_type" = "hnsw", "max_degree" = "32", "metric_type" = "inner_product") ) ENGINE=OLAP DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES ( "replication_allocation" = "tag.location.default: 1", "storage_medium" = "hdd", "storage_format" = "V2", "inverted_index_storage_format" = "V3", "light_schema_change" = "true" );说明：若计划使用 SDK 一键建表与导入（见 ⑤），本节可省略。（3）演示语料示例使用 Apache Doris 官网文档作为语料来源：https://github.com/apache/doris-website（4）离线文档处理切块（chunking）：采用重叠分割，将长文档切分为段落片段。from langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=400, chunk_overlap=100, length_function=len ) chunks = text_splitter.split_text(text)生成向量（embedding）：对每个片段生成嵌入向量。from typing import List, Dict from langchain_community.embeddings import OllamaEmbeddings embeddings = OllamaEmbeddings(model='bge-m3:latest', base_url='http://localhost:11434') docs: List[Dict] = [] cur_id = 1 for chunk in chunks: docs.append({"id": cur_id, "content": chunk}) cur_id += 1 contents = [d["content"] for d in docs] vectors = embeddings.embed_documents(contents)（5）导入 Doris（方式二：SDK 一键建表与导入）import pandas as pd df = pd.DataFrame( [ { "id": d["id"], "content": d["content"], "embedding": vec, } for d, vec in zip(docs, vectors) ]) from doris_vector_search import DorisVectorClient, AuthOptions, IndexOptions auth = AuthOptions( host='localhost', query_port=9030, http_port=8030, user='root', password='', ) client = DorisVectorClient('doris_rag_test_db', auth_options=auth) index_options = IndexOptions(index_type="hnsw", metric_type="inner_product") table = client.create_table( 'doris_rag_demo', df, index_options=index_options, )说明：若已通过 ② 使用 SQL 创建好表并定义索引，可仅使用 SDK 的导入接口（如 insert/load 等，视 SDK 能力而定）将数据写入既有表。（6）在线查询过程向量检索query = 'Doris 支持哪些存储模型？' query_vec = embeddings.embed_query(query) df = ( table.search(query_vec) .limit(5) .select(["id", "content"]) .to_pandas() )答案生成ctx = "\n".join(f"{r['content']}" for _, r in df.iterrows()) prompt = "以下是检索到的 Doris 文档片段：\n\n{}\n\n请根据上述内容回答：{}".format(ctx, query) from langchain_openai import ChatOpenAI llm = ChatOpenAI( model='deepseek-v3-1-terminus', api_key='xxxx', base_url='https://xxx', temperature=float(1.0)) resp = llm.invoke(prompt)返回的内容是：'根据提供的文档内容，Apache Doris 支持以下三种存储模型：\n\n1. 明细模型（Duplicate Key Model）：适用于存储事实表的明细数据。\n2. 主键模型（Unique Key Model）：保证主键的唯一性，相同主键的数据会被覆盖，从而实现行级别的数据更新。\n3. 聚合模型（Aggregate Key Model）：相同键（Key）的数值列（Value）会被自动合并，通过提前聚合来大幅提升查询性能。\n\n此外，文档在“灵活建模”部分还提到，Apache Doris 支持如宽表模型、预聚合模型、星型/雪花模型等建模方式，这些可以看作是建立在上述三种核心存储模型之上的数据组织方法。'5. 总结本文从 AI 时代的数据形态演进出发，系统性地介绍了 Apache Doris 在 4.x 版本中引入的向量检索能力，并对其底层实现进行了深入剖析。从 ANN 索引的能力边界，到 FE / BE 架构下的写入、构建与查询路径，再到 SIMD、压缩编码与执行引擎层面的工程优化，Doris 的向量搜索并非简单接入一个索引库，而是围绕 性能三角（召回率 / 查询延迟 / 构建吞吐） 精心设计的系统级方案。未来，我们还会进一步强化，使其成为 AI 时代数据系统智能检索的基石。
从 Greenplum 到 Doris：集群缩减 2/3、年省数百万，度小满构建超大规模数据分析平台技术实践
度小满引入 Apache Doris 替换原有 Greenplum，实现整体查询效率提升 82%，与此同时，集群缩减 2/3、年省数百万的巨大效益。本文将分享度小满如何基于 Doris 从 0 到 1 构建超大规模数据分析平台，并围绕平滑迁移、异地多活容灾等方面，分享实践经验。本文整理自度小满 Doris 数据库负责人汤斯在 Doris Summit 2025 中的演讲，并以演讲者第一视角进行叙述。度小满金融（原百度金融）作为一家覆盖现代财富管理、支付、金融科技等多板块的科技公司，数据的分析处理对其极为重要，已经深度融入业务生命周期的每个环节，是进行风险控制、商业决策、用户体验优化及运营提效的基石。随着业务高速发展，度小满原有基于 Greenplum 搭建的 OLAP 平台，逐渐暴露出三大痛点：规模与稳定性瓶颈：存储已接近饱和，扩容至百余台已接近硬件规模的承载上限，如果继续扩容，将面临更严重的稳定性挑战。性能与体验不佳：Greenplum SQL 查询执行速度慢，且经常出现 “计算时间远小于排队时间” 的情况，严重影响业务分析效率。缺失技术支持：当前使用的 Greenplum 6 版本技术架构已显得陈旧，并且 2024 年 Greenplum 宣布将停止开源，后续的技术支持与迭代升级将无法保障。为了应对这些痛点，度小满金融迫切寻找更为高效、稳定且具备现代化技术架构的数据处理解决方案，以支持其未来的业务发展。Apache Doris：高吞吐、快查询面对日益增长的业务体量与复杂多变的分析需求，选用一个高效、可靠的数据库系统，已成为支撑业务稳健发展与快速创新的关键。Apache Doris 以其出色的性能表现与高度灵活的架构，成为众多场景下的优选方案。为深入验证其在海量数据与复杂分析场景中的能力，我们展开了一系列性能测试，关键结果如下：查询性能：在 1TB TPC-DS 标准测试集中， Apache Doris的查询速度约是 Greenplum 6 的 20-30 倍。导入性能：在基于 Flink 写入的 TPS 测试中，基于单分片导入，压测最大 TPS 为：5000W/s。JSON 数据处理：针对新推出的 Variant JSON 数据类型，测试显示：存储 2-3 万 Key 时，其空间占用仅为普通 JSON 的 1/10 甚至更低，查询效率则提升至 10 倍以上。综上可知，Apache Doris 在写入吞吐、响应速度及存储效率上表现卓越，有力证明了其应对大规模、实时化、半结构化数据分析挑战的坚实技术基础。基于 Apache Doris 的大规模数据分析平台在上述详实的选型调研之后，我们决定采用 Apache Doris 替代原有 Greenplum 集群，构建超大规模数据分析平台。为验证 Apache Doris 在真实业务场景中的表现，我们先进行了小范围试点，部署了少量 Doris 集群，并先行接入几个关键业务方。试点期间，系统在性能、稳定性和易用性方面获得高度评价。基于这一积极反馈，我们稳步扩展 Doris 集群规模，最终在效率与成本上实现大幅提升：整体效率：端到端分析任务耗时从 274 秒降至 47 秒，效率提升 82%，任务超时查杀比例从 1.3%骤降至 0.11%，降幅达 91%，彻底解决高峰期排队问题实现 0 排队，使分析师的工作不再因拥堵而中断，体验和生产力均有极大提升。集群成本：在同等资源成本下， Doris 仅以 1/3 的集群数量即可提供与 Greenplum 同等的服务能力，存储性能提升 200%。截至目前，已完成 百余台原 Greenplum 服务器的清退工作，以更少的硬件资源支撑了更高的计算与存储需求，实现年度硬件成本节约数百万元。从 0-1 数据平台建设经验我们基于 Apache Doris 成功替换了 Greenplum，完成了从 0-1 的数据平台重构，覆盖架构设计、数据流转与业务协同的系统性工程。以下将围绕快速平滑迁移、异地多活容灾与全链路生态集成三个核心环节，展开具体实践。01 快速迁移为保障业务连续性与数据安全，我们开发了自动化迁移工具 SqlGlot，将大规模数据从原有 GP 集群迁移至 Doris 集群。整个过程历经半年，累计迁移 PB 级规模数据，全程业务无感知。表结构迁移：在表结构迁移阶段，团队从 GP 系统中导出表结构及相关元数据，借助 SqlGlot 工具实现字段映射与语法适配，并在此基础上完成分区构建与分桶策略设计，确保每个分桶数据量控制在 1G～3G 的合理范围内。该流程最终成功转换超过 20,000 张表，并保障了所有表的分区与分桶结构符合业务与性能要求。表数据迁移：我们通过分布式导出将 GP 数据并行迁移至 Doris 机器，并基于 Doris 官方推荐的 Stream Load 进行并发控制，以文件流式加载的方式高效导入数据至 Doris 集群。整个过程累计完成 PB 级规模数据迁移，稳定支持了 5000+ 次数据同步任务。SQL 迁移：为解决因业务规模庞大、场景复杂而导致的官方工具语法支持不全的问题，我们基于 SqlGlot 并结合正则匹配能力，将 PostgreSQL SQL 高效转换为 Doris SQL。整个迁移流程包括“转换成功 → 执行成功 → 数据一致” ，累计完成约 47 万个 SQL 的转换，实现 95% 的执行成功率 与 92% 的数据一致率。02 异地双机房灾备为保障数据安全并实现集群高可用，我们基于 Apache Doris 构建了异地双机房灾备架构，确保数据与服务具备跨机房容灾与双活能力。核心设计如下：我们将所有 Doris 集群节点均匀部署于 A 与 B 两个异地机房，通过设置 tag.location 属性明确节点所属机房。用户账号按机房绑定，访问请求通过轮询机制自动分配，实现负载均衡（例如首次请求路由至 A 机房，第二次则路由至 B 机房）。建表时通过配置 location 参数，确保每张表在双机房各保留 2 个副本，从而达成数据异地双活与故障自动切换。关键配置示例：设置节点机房标签alter system modify backend ”BE1:9050" set ("tag.location" = "group_a");alter system modify backend ”BE2:9050" set ("tag.location" = "group_b");复制代码建表时指定双机房副本分布CREATE TABLE ubevent (ts DATETIME, uid INT, ...) DUPLICATE KEY(ts) DISTRIBUTED BY HASH(uid) BUCKETS 10PROPERTIES ("replication_allocation" = "tag.location.group_b: 2, tag.location.group_a: 2");复制代码03 生态整合为构建高效、稳定、易用的数据平台，我们还围绕 Apache Doris 进行系统性生态整合：计算引擎无缝集成：通过 Doris 官方提供的 Spark Connector 与 Flink Connector，实现了与现有 Spark、Flink 计算引擎的高效对接，保障了数据流水线稳定运行。运维体系化与自动化：集成 Prometheus、Grafana 及 Doris Manager，构建了覆盖监控、告警、管理与调优的自动化运维体系，全面提升集群稳定性与运维效率。优化经验为进一步提升数据平台的效率及资源利用率，在实际落地过程中，围绕集群、负载、存储等多维度总结了以下优化经验：01 集群隔离当前我们有多个 Doris 集群，为合理承接不同业务方的接入需求，我们主要依据业务成本与稳定性要求两大维度进行评估与路由。通常而言，稳定性越高，对应成本也越高。新建集群时，稳定性最优，但相应成本也最高。为在成本与稳定性之间取得平衡，我们大多场景是基于 Workload Group 资源硬隔离方案，对 CPU 与内存进行资源组级别的隔离，有效减少不同业务负载间的资源竞争。若业务对稳定性的要求超出共享集群所能提供的范围，则仍需要通过新建独立集群来满足。02 存储压力在 Apache Doris 的落地与运维过程中，我们曾面临因业务快速增长带来的高达 80%-90% 的磁盘存储压力。针对这一问题，进行了一系列优化：控制表生命周期：部分业务或因对动态分区相关语法不熟悉，未主动采用该策略。为此，集成动态分区的参数配置，简化了开发难度，并提供统一注册入口，业务开发人员仅需选择是否开启、保留天数即可。修改压缩格式：将默认压缩算法从 LZ4 切换为 ZSTD。实测表明，存储空间平均节省约 50%，虽带来约 20%～30% 的 CPU 与内存负载上升，但整体 ROI 仍然较高。存储指标监控告警：为预防因误操作或异常行为导致的存储激增，建立了针对“人员”与“表”双维度的监控体系。环比分析业务人员数据占用趋势及单表每日增长量，可自动识别异常（如单日增长飙升至日常 10 倍），并及时触发告警及通知。Hive 与 Doris 打通：在基于 Kerberos 认证的 Hive 环境中，对 Doris Hive Catalog 功能进行了二次开发，实现跨系统的直接数据访问，无需依赖 Flink 等同步工具，简化了架构并提升了数据使用效率。03 负载均衡为确保系统在负载高峰期的稳定运行，特别是应对异常 SQL 与大查询带来的资源压力，应对措施如下：双机房负载均衡：基于已有的异地双机房架构，通过轮询机制实现业务流量在 A 与 B 机房之间的自动分发：首个 SQL 请求路由至 A，次个请求则导向 B，以此循环，确保双机房负载均衡，避免单点资源过载。SQL 参数限制：通过 enable_query_memory_overcommit = false、exec_mem_limit = 256 * 1024 * 1024 * 1024 等参数将最大占用内存限制为 256G，避免集群被打满，后续计划降至 60G。Workload 资源队列动态调整：基于任务类型划分资源队列，配置 CPU 的软隔离和内存的硬隔离，并支持错峰调度。比如：例行任务通常在夜间执行，为其创建专门资源队列，数据分析等公共任务大多在白天执行，将配置更大的资源队列，随着白天/夜间需求的变化动态调整资源。此外，依据各队列负载设定并行度与并发数，控制任务排队时长。异常 SQL 拦截：实时识别与拦截异常 SQL，避免其影响 BE 节点稳定性。初期使用 Doris 内置正则规则进行拦截，但规则复杂导致 CPU 开销上升。为此，我们将拦截逻辑外移至平台层执行，以避免正则匹配及超大 JOIN 导致的 CPU 负载过高。04 集群稳定性随着集群规模不断扩大，保障 FE、BE 节点稳定性成为运维工作的核心挑战，为此，我们构建了以下保障体系：分层触达+全维度覆盖：根据不同指标优先级设置通知电话、短信、飞书提醒，P0 监控准确率 ≥80%；自动异常处理：为 FE 和 BE 的宕机重启设置了自动化处理方案，在识别到服务卡住时，系统会自动重启进程。此外，对于磁盘掉线，将自动下线故障盘并触发副本补齐。我们同时采用对战分析、火焰图和日志查看等方法进行详细记录，以便后续调优。此外，编写了 SOP 手册，涵盖不同场景的应对措施，并进行了异常处理演练。结束语截至目前，我们已搭建 3 个基于 Doris 2.1.10 版本的线上集群，其中最大规模的集群达万 core 级别、上百 TB 内存和 PB 级磁盘。目前仍在扩容中，计划在年底前新增百余台 CN 节点和数十台 Mix 节点。未来，我们将重点关注并探索以下能力：存算分离：重点关注 Doris 3.X 版本的存储分离架构，推动落地实践。湖仓一体：全面打通数据湖与数据仓库，目前已小规模试点 Paimon；此外，针对数据外置场景，计划通过异步物化视图提升查询性能。智能物化视图探索：引入语义建模与 AI 智能分析，降低研发与业务沟通门槛，并对智能推荐与模板化方案进行探索与实践。