在与客户交流过程中,我们曾遇到一家电商企业,其分析数据规模已达到 80TB。为了支撑不同业务场景,团队分别部署了仪表盘、商品搜索和向量检索三套独立系统。随着业务发展,系统间的数据同步、运维和故障排查成本持续增加,维护多套系统逐渐成为新的挑战。最终,该团队基于 Apache Doris 完成了相关能力的统一建设,在满足业务需求的同时,也显著降低了系统复杂度。
类似的情况在企业数字化建设过程中并不少见。当分析业务不断演进、系统持续增加时,团队往往需要重新评估现有架构是否仍然适合业务发展。在着手重构之前,更值得思考的是:当前面临的问题是否已经达到需要引入新技术栈、投入额外资源解决的程度。如果答案是肯定的,希望本文能够为相关技术选型和架构演进提供一些参考。
架构设计有一个重要原则:技术栈的复杂度应与团队的运维能力和业务规模保持匹配。每引入一套新的系统,都意味着额外的部署、监控、运维、故障排查以及人才投入成本。因此,在满足业务需求的前提下,构建适配当前发展阶段的最小可行基础设施(Minimum Viable Infrastructure,MVI),通常是更具长期价值的选择。
如何判断 PostgreSQL 是否面临性能瓶颈?
扩展性问题通常不会突然出现,而是随着业务规模和数据量增长逐步显现。
随着分析负载不断增加,团队往往会优先采用成本较低、改动较小的优化手段,例如增加索引、表分区、反规范化设计、物化视图、只读副本,以及 Citus 等分片方案。这些措施通常能够在一定程度上缓解当前问题,但随着优化手段不断叠加,系统架构也会逐渐复杂,后续维护和扩展成本随之增加。
实践中,很多团队最终会发现,真正的瓶颈并不在于缺少更多优化手段,而是在于 PostgreSQL 主要面向单机架构设计,对于持续增长的分布式分析负载,其扩展能力存在一定局限。
当然,在引入新的技术方案之前,更重要的是确认当前是否已经出现了典型的分析型性能瓶颈。可参考下表自查:

同时建议在 PostgreSQL 的只读副本上执行以下查询,用于分析当前表扫描情况:
SELECT schemaname,
relname,
seq_scan,
seq_tup_read,
idx_scan,
idx_tup_fetch,
CASE
WHEN seq_scan > 0 THEN seq_tup_read / seq_scan
ELSE 0
END AS avg_rows_per_seq_scan
FROM pg_stat_user_tables
WHERE seq_scan > 100
AND seq_tup_read / GREATEST(seq_scan, 1) > 100000
ORDER BY seq_tup_read DESC
LIMIT 10;
如果查询结果显示,部分表在顺序扫描时平均需要读取超过 10 万行数据,通常意味着分析型查询已经大量依赖全表扫描。对于这类场景,列式存储数据库通常能够获得数量级的性能提升,因为其存储和执行模型针对大规模扫描进行了专门优化。
很多团队在发现这一现象后,第一反应往往是继续增加 PostgreSQL 只读副本,希望通过横向扩展缓解压力。
为什么只读副本无法解决这一问题?
而只读副本能够提升系统的查询并发能力,但通常无法显著改善单条分析查询的执行性能。这种差异,本质上源于 OLTP 数据库与 OLAP 数据库在架构设计上的不同,差异总览如下。

行存储与列存储的对比
PostgreSQL 采用行存储(Row Store)架构,其设计目标是高效读取完整记录,因此非常适合事务处理场景。
例如,当一个包含 50 个字段的数据表,仅需要查询其中 2 个字段用于报表分析时,PostgreSQL 仍然需要从磁盘读取完整的数据行,再丢弃未使用的字段,这意味着实际读取的数据量远高于查询所需的数据量。
列式数据库则采用完全不同的存储方式,每一列独立存储,仅加载查询涉及的列,因此能够显著减少分析查询的 I/O 开销。
此外,列存储通常具有更高的数据压缩率。由于同一列中的数据类型一致、数据分布更加集中,列式数据库通常能够实现 5~10 倍的数据压缩,而传统行存储的压缩率通常约为 2~3 倍。
近年来,Citus Columnar、Mooncake 等 PostgreSQL 扩展也引入了列存储能力,用于改善分析场景下的查询性能。但这些能力仍然建立在 PostgreSQL 行存储架构之上,而不是数据库的默认存储模型。
逐行执行与向量化执行的区别
除了存储方式之外,查询执行模型也是影响分析性能的重要因素。
PostgreSQL 采用逐行执行(Row-based Execution)模式,每一行数据都需要独立完成表达式计算、条件过滤以及聚合等操作。
现代分析型数据库普遍采用向量化执行(Vectorized Execution),一次处理数千条数据,并利用 CPU SIMD 指令集批量完成表达式计算。
对于千万级数据扫描任务,向量化执行能够显著减少函数调用和 CPU 开销,在实际分析场景中通常能够带来数倍甚至数量级的性能提升。
单节点规划与分布式规划的差异
PostgreSQL 的查询优化器主要针对单机架构设计,一条 SQL 查询只能在单个实例上执行。即使部署了多个只读副本,也无法将同一条查询拆分到多个副本上并行计算。因此,增加只读副本能够提升的是同时处理更多查询的能力,而不是提升单条查询的执行速度。
分析型数据库则采用分布式查询规划器,能够自动将一条大型查询拆分到多个计算节点并行执行。
例如,对于一条需要扫描 1TB 数据的查询,如果集群拥有 10 个计算节点,那么每个节点可以并行处理约 100GB 的数据,最终由协调节点汇总计算结果。在数据分布均衡的情况下,随着节点数量增加,单条查询的执行时间也能够相应缩短。
综上所述,单纯增加只读副本,通常只能提升查询并发能力,难以解决单条大规模分析查询的执行效率问题。当分析负载逐渐成为系统的主要压力来源时,引入专门面向分析场景设计的数据库,通常是更合适的选择。
不过,实践中我们也发现,不少团队在数据库选型时过于关注基准测试成绩,而忽略了业务实际依赖的数据能力。迁移完成后才发现,新系统无法覆盖 PostgreSQL 开箱即用提供的一些能力。
明确业务所依赖的 PostgreSQL 能力
虽然 PostgreSQL 通常被定位为 OLTP 数据库,但在实际业务中,它往往也承担了部分实时分析任务。
数据库系统通常可以分为两类:一类面向 OLTP,强调高并发事务处理和低延迟响应;另一类面向离线分析,强调大规模数据处理和分析吞吐能力。而越来越多企业需要的是介于两者之间的实时分析能力,即支持实时数据写入,并能够针对最新数据进行低延迟分析。
正因如此,很多团队虽然将 PostgreSQL 作为业务数据库使用,但实际上已经依赖了它提供的一系列实时分析能力。
- 亚秒级数据新鲜度: PostgreSQL 主从复制延迟通常控制在秒级以内,BI 仪表盘和运营后台展示的通常是实时数据,而非 10 分钟之前的历史数据。
- 实时更新:当业务数据发生更新时,例如订单状态由"待处理"变为"已发货",变更能够立即同步至分析查询,无需等待批处理任务或下一轮 ETL。
- 支持事务的轻量 ETL:执行
INSERT INTO summary_table SELECT ... FROM orders GROUP BY ...,语句要么完全执行成功,要么完全执行失败。部分写入不会导致聚合数据损坏。 - 多表关联:对于订单、客户、商品、物流等业务数据,开发人员通常只需编写一条 SQL,查询优化器即可完成关联规划,无需额外考虑数据关联方式。
- 全文检索:借助
tsvector和tsquery,PostgreSQL 可以支持日志、商品描述、用户评论等文本数据的全文检索,无需额外部署独立搜索系统。 - 向量检索:借助
pgvector,可以运行语义搜索和 AI 驱动的功能。向量数据能够与关系型数据统一存储和管理,无需引入独立的向量数据库。
不少团队直到完成迁移后,才意识到部分业务已经建立在这些能力之上。因此如果前期缺乏充分评估,迁移过程中往往需要调整数据模型,甚至重构数据处理流程,从而增加迁移成本和项目周期。
不同分析型数据库在查询性能、实时更新、事务支持、复杂关联等方面各有侧重。在数据库选型过程中,要明确业务真正依赖哪些 PostgreSQL 能力,并评估目标系统是否能够满足这些需求。
为什么选择 Apache Doris?
基于上述能力要求,下表对几类主流方案进行对比。
该表用于说明不同产品类型的典型设计侧重,具体能力可能因产品版本、部署模式和使用方式而有所差异。

从这个角度来看,不同类型数据库都有各自擅长的场景。而当业务既要求亚秒级数据新鲜度,又依赖实时更新、事务以及复杂关联查询时,单独采用上述两类方案往往都存在一定局限。
Apache Doris 是一款能够同时兼顾实时分析和丰富数据能力的统一分析平台。

Apache Doris 的设计目标之一,就是在提供高性能实时分析能力的同时,尽可能保留企业已经习惯使用的数据能力,降低数据库迁移和架构演进成本。
对于前文提到的电商团队,迁移至 Apache Doris 后,原有多套分析系统得以统一,整体架构和运维链路随之简化。与此同时,在 PostgreSQL 中需要大量人工规划的部分能力,例如数据分区、分布式扩展、存储管理以及高可用机制,也能够通过 Apache Doris 的原生分布式架构统一实现。

当然,Apache Doris 也并非适用于所有场景。
首先,作为一款分布式分析型数据库,Apache Doris 相比单机数据库具有更高的运维复杂度。如果团队此前没有分布式数据库的运维经验,需要预留一定的学习和实践成本,包括集群部署、资源规划、性能调优以及日常运维等工作。对于希望兼顾实时分析能力和托管体验的团队,也可以考虑使用 SelectDB等托管版 Apache Doris 服务。
其次,对于数据规模较小、分析负载有限的业务场景,PostgreSQL 配合索引优化和只读副本通常已经能够满足需求。此时,引入分布式分析数据库反而可能增加系统复杂度和运维成本。
推荐的迁移架构
对于大多数企业而言,更推荐采用 OLTP 与 OLAP 分层的架构。
┌─────────────────┐ ┌─────────────────┐
│ PostgreSQL │ CDC │ Apache Doris │
│ (OLTP) │ ──────> │ (OLAP) │
└─────────────────┘ └─────────────────┘
│ │
业务事务写入 BI 分析
在线业务 即席查询
全文检索
向量检索
在这一架构中,PostgreSQL 继续承担事务处理和业务写入,Apache Doris 负责分析型查询,两者通过 CDC 保持数据实时同步,实现业务与分析解耦。

对于希望快速完成 PostgreSQL 分析负载迁移的团队,Doris 内置 PostgreSQL CDC 提供了更加简化的一站式同步方案。用户可以直接通过 SQL 创建持续同步任务,将 PostgreSQL 中的全量数据及后续 WAL 变更同步至 Doris,无需额外部署 Kafka、Flink 或 Spark 等外部组件。
渐进式架构演进路径
那么,随着数据规模增长,架构如何演进?不同阶段对数据库能力的要求并不相同,建议根据业务规模逐步演进,而不是一次性引入复杂架构。
低于 10 TB:推荐 PostgreSQL(1 套系统)
这一阶段,PostgreSQL 配合索引优化、分区以及只读副本通常已经能够满足业务需求,无需额外部署分析系统。
10 TB 至 1 PB:PostgreSQL + Apache Doris(两套系统)
PostgreSQL 负责事务处理,Apache Doris 统一承担分析型工作负载,包括 BI 仪表盘、即席分析、全文检索、向量检索以及轻量级 ETL。对于大多数企业而言,两套系统即可覆盖绝大多数业务需求。
超过 1 PB:PostgreSQL + Apache Doris + 批处理层(共 3 个系统)
随着数据规模进一步增长,实时分析与离线计算通常会逐渐分层:
- Apache Doris:负责实时分析、仪表盘、交互式查询以及低延迟数据服务。
- Spark、Snowflake、Databricks 等平台:负责大规模 ETL、历史数据重处理以及复杂离线计算。
此时,引入第三套系统是为了满足新的业务需求,而不是过早增加架构复杂度。
总结
PostgreSQL 仍然是一款优秀的 OLTP 数据库。对于分析负载有限的业务,通过索引优化、分区以及只读副本,通常已经能够满足需求,没有必要过早引入新的技术栈。
当数据规模和分析需求持续增长,仅依靠 PostgreSQL 难以兼顾事务处理与实时分析时,采用 PostgreSQL + Apache Doris 的 OLTP 与 OLAP 分层架构,能够在保留现有业务系统的基础上,构建面向实时分析的数据平台。
数据库迁移并不是简单地替换一款产品。相比关注基准测试中的性能数字,更重要的是结合真实业务负载,验证目标系统是否能够满足实时更新、多表关联、全文检索、向量检索等核心需求。
更多关于 Apache Doris 的产品能力、部署实践和最佳实践,可参考 Apache Doris 官方文档并参与社区交流;如果希望进一步体验云原生托管版本,也可以了解 SelectDB 提供的相关服务。