ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

AnalyticDB vs Doris/StarRocks:真实业务毛刺下的数仓稳态性能实测

AnalyticDB vs Doris/StarRocks:真实业务毛刺下的数仓稳态性能实测

1. 项目概述:一场不带滤镜的数仓性能实测,为什么这次我们没选开源方案?

“瑶池数据库 AnalyticDB MySQL 性能Benchmark:全面优于开源自建数仓”——这个标题不是宣传稿,是我上个月在某中型互联网公司数据平台组做的一次封闭式压测报告的核心结论。当时团队正面临一个典型困境:用 Apache Doris 搭建的自建实时数仓,在双十一大促期间 QPS 突增 3.2 倍后,查询平均延迟从 800ms 拉升到 4.7s,且连续三天出现 5% 的超时失败率;而业务方提出的“用户行为路径秒级下钻”需求,Doris 集群在 12 亿行事实表 + 8 张维度表关联场景下,稳定响应时间始终卡在 2.1s 左右,远超产品定义的 800ms SLA。我们没急着扩容节点,而是拉出三套环境做了横向对比:一套维持现状的 Doris 2.0.6(16 节点,SSD 存储),一套新部署的 StarRocks 3.1(同规格硬件),第三套是刚接入的瑶池数据库 AnalyticDB MySQL 版(8 节点,计算存储分离架构)。测试不是跑 TPC-DS 这种教科书式 Benchmark,而是直接把过去三个月真实脱敏的 17 个高频 SQL 模板(含窗口函数、多层嵌套子查询、大表 Join、Bitmap 去重等)灌进去,每条 SQL 并发 50 路,持续压测 90 分钟。结果出来那天,运维同事盯着监控面板看了三分钟没说话——AnalyticDB 在所有 17 条 SQL 中,P95 延迟全部低于 620ms,资源利用率峰值仅 68%,而 Doris 同一时刻 CPU 打满、磁盘 IO 等待队列堆积到 142,StarRocks 则在第 7 条 SQL(涉及 5 表关联+时间窗口聚合)上首次出现超时。这不是“云厂商吹牛”,而是我们在真实业务毛刺里抠出来的数据。如果你正被自建数仓的稳定性、扩缩容成本或复杂 SQL 支持度困扰,这篇记录会告诉你:当“开源自建”不再等于“技术正确”,你该关注什么底层能力,而不是只看 GitHub Stars 数。

2. 核心设计思路拆解:为什么 Benchmark 不是比谁跑得快,而是比谁扛得住毛刺?

2.1 测试目标的本质重构:从“峰值吞吐”转向“稳态可用性”

很多团队做数仓 Benchmark,第一反应是跑 TPC-DS 或 ClickBench,追求单条 SQL 的最快执行时间。这就像买车只测百公里加速,却不管高速巡航时的油耗和底盘抖动。我们这次彻底放弃这种思路,核心目标定为“在业务流量毛刺下维持 P95 延迟不破防”。为什么?因为真实线上场景里,99% 的问题不出现在平稳期,而出现在流量突增的 30 秒内。比如某次促销活动,用户点击“查看优惠券”按钮的请求量在 2 秒内从 200 QPS 暴涨到 3800 QPS,后台数仓要实时聚合优惠券核销率、地域分布、用户分层转化率——这 3 个指标对应 3 条 SQL,但它们共享同一张 20 亿行的核销明细表。如果数仓引擎不能快速复用中间结果、无法动态调整内存分配、或者锁表机制僵硬,就会像多米诺骨牌一样连锁超时。所以我们的测试设计强制包含三个关键维度:

  1. 毛刺注入:在压测进行到第 30 分钟时,手动触发一次 5 倍流量突增(模拟突发事件),持续 90 秒;
  2. 混合负载:17 条 SQL 不是轮流执行,而是按真实业务比例混合并发(如 40% 是单表聚合,30% 是星型模型 Join,20% 是窗口分析,10% 是高基数去重);
  3. 长稳验证:每轮压测后,不做任何重启,直接进入下一轮,连续跑满 3 轮(共 4.5 小时),观察资源泄漏和查询退化趋势。

提示:很多开源方案在首轮压测表现不错,但到第三轮时,Doris 的 BE 节点 JVM Full GC 频次上升 300%,StarRocks 的 Tablet 元数据锁竞争导致部分查询排队超 5 秒——这些细节在单轮 Benchmark 里根本看不到。

2.2 架构选型逻辑:为什么 AnalyticDB MySQL 版能“降维打击”自建方案?

看到“全面优于”这个词,很多人第一反应是“云厂商肯定作弊”。但实际拆解下来,AnalyticDB 的优势不是来自参数调优,而是架构基因差异。我们可以用一个生活化类比理解:自建 Doris/StarRocks 就像自己组装一台高性能游戏电脑——你得买 CPU、显卡、内存、散热器,再一层层装驱动、调 BIOS、优化电源策略;而 AnalyticDB 是一台预装好所有专业软件、经过千场电竞比赛验证的整机,它的“主板”(存储计算分离)、“散热系统”(智能内存管理)、“BIOS 固件”(SQL 优化器深度集成 MySQL 协议)都是为 OLAP 场景原生设计的。具体到本次测试,三个底层能力形成组合拳:

  • 计算存储分离的弹性水位线:AnalyticDB 的计算节点不存数据,只管算。当毛刺来临时,它能瞬间从集群池里调度空闲计算资源(毫秒级),而 Doris 的每个 BE 节点既是计算又是存储,扩容必须同步迁移数据(小时级),扩容期间查询必然抖动;
  • MySQL 协议栈的语义红利:AnalyticDB 完全兼容 MySQL 5.7 协议,这意味着它的优化器能直接复用 MySQL 社区十年积累的统计信息收集逻辑、索引选择策略、Join 重排算法。我们一条含GROUP BY user_id, DATE(event_time)的 SQL,在 Doris 里需要手动建物化视图加速,在 AnalyticDB 里加个普通二级索引就搞定,且索引更新是实时的;
  • 向量化执行引擎的“无感加速”:AnalyticDB 的执行引擎深度向量化,但对用户完全透明。它不像 StarRocks 需要手动开启enable_vectorized_engine参数,也不像 Doris 要区分vectorized和non-vectorized模式。我们压测时甚至没意识到这点,直到看执行计划发现:同样一条COUNT(DISTINCT user_id),AnalyticDB 自动用了 Roaring Bitmap + SIMD 指令加速,而 Doris 默认走 Hash Aggregate,CPU 利用率高出 22%。

2.3 为什么不开源方案“输”在工程细节而非理论性能?

很多人误以为开源数仓性能差是因为算法落后。其实不然。Doris 的 MPP 执行框架、StarRocks 的 CBO 优化器,理论性能都极强。但“理论”和“线上”之间隔着一堵叫“工程鲁棒性”的墙。我们这次测试暴露出三个致命细节差距:

  1. 元数据服务的单点脆弱性:Doris 的 FE(Frontend)节点承担元数据管理、查询规划、集群协调三重角色。压测中当 FE 节点 CPU 达到 92% 时,新提交的查询开始排队,排队时间呈指数增长。而 AnalyticDB 的元数据服务是独立高可用集群,计算节点只读取元数据缓存,即使元数据服务短暂抖动,已建立的连接不受影响;
  2. 内存管理的“野蛮生长” vs “精耕细作”:Doris 的内存分配依赖 JVM 堆,BE 节点一旦 OOM 就整个进程挂掉;StarRocks 用 C++ 自管内存,但存在内存碎片化问题,长时间运行后小内存分配失败率上升。AnalyticDB 则采用“分级内存池”:查询内存、缓存内存、网络缓冲区内存物理隔离,且每类内存有独立的 LRU 和淘汰策略,压测 4.5 小时后,各内存池使用率波动始终控制在 ±3% 内;
  3. 日志与监控的“事后诸葛亮” vs “事前预警”:Doris 的慢查询日志只记录执行完的 SQL,无法定位“为什么慢”;StarRocks 的 Profile 信息虽全,但需人工解析 Flame Graph。AnalyticDB 的监控体系直接对接 SQL 执行生命周期:从 Parser 阶段的语法树生成耗时、到 Optimizer 阶段的候选计划评估次数、再到 Executor 阶段各算子的 CPU/IO/Network 消耗,全部自动打点。我们正是靠这个功能,30 分钟内定位到 Doris 在某条 SQL 上因统计信息过期导致 Join 顺序错误,从而针对性修复。

3. 核心实操环节详解:从环境搭建到压测脚本,一份可直接抄作业的全流程

3.1 环境准备:硬件规格统一,杜绝“配置陷阱”

Benchmark 最怕“田忌赛马”。我们严格遵循“同规格、同网络、同数据”三原则:

  • 硬件配置:全部采用阿里云 ecs.g7ne.4xlarge 实例(16 vCPU / 64 GiB 内存 / 2 * 3.8 TB NVMe SSD),操作系统统一为 Alibaba Cloud Linux 3.2104 LTS;
  • 网络环境:三套集群部署在同一 VPC、同一可用区,通过内网直连,避免公网延迟干扰;
  • 数据集:使用某电商平台脱敏后的 30 天用户行为日志(原始数据 12TB),经 ETL 清洗后生成标准星型模型:1 张事实表(fact_user_event,22 亿行)、4 张维度表(dim_user、dim_product、dim_region、dim_time),所有表均按时间分区,分区粒度为天;
  • 版本锁定:
    • Doris:2.0.6(Commit ID: doris-2.0.6-rc01)
    • StarRocks:3.1.0(Build ID: starrocks-3.1.0-rc02)
    • AnalyticDB MySQL:内核版本 8.0.2(对应瑶池数据库最新 GA 版)

注意:特别提醒,StarRocks 官方推荐的最小部署规格是 8C16G,但我们坚持用 16C64G 规格,就是为了排除“资源不足导致性能失真”的质疑。实测下来,StarRocks 在该规格下仍比 AnalyticDB 多消耗 37% 的 CPU 资源。

3.2 数据加载与索引构建:让“公平起跑线”真正落地

数据加载不是简单INSERT INTO ... SELECT,而是考验引擎对批量写入的优化能力。我们采用统一的数据导入方式:

  • Doris:使用 Stream Load 接口,将 Parquet 文件分片上传,curl -X PUT --data-binary @chunk_001.parquet "http://doris-fe:8030/api/db_name/table_name/_stream_load",并设置{"format":"parquet","strip_outer_array":true};
  • StarRocks:使用 Broker Load,通过LOAD LABEL db_name.label_20240501 (DATA INFILE("hdfs://namenode:8020/data/chunk_001.parquet") INTO TABLE table_name)导入;
  • AnalyticDB MySQL:使用INSERT /*+ PARALLEL(32) */ INTO table_name SELECT * FROM oss_table,其中oss_table是通过 OSS Foreign Table 创建的外部表,指向同一份 Parquet 文件。

关键差异在于索引构建策略。我们为所有引擎在事实表上创建了相同的业务索引组合:

字段组合Doris/StarRocks 方案AnalyticDB MySQL 方案说明
(event_date, user_id)创建 Rollup 表 / 物化视图创建联合二级索引Rollup 表需额外存储空间,且变更需重建;二级索引自动维护
(product_id, event_type)创建 Bitmap 索引创建普通二级索引 +INDEX_HINTBitmap 索引对高基数字段效果差,AnalyticDB 的索引 Hint 可强制走索引
user_id(高基数)无特殊处理创建前缀索引INDEX idx_uid_prefix (user_id) COMMENT 'prefix_length=8'避免全索引扫描,AnalyticDB 支持前缀长度自定义

实测数据加载耗时(22 亿行):

  • Doris:2 小时 18 分钟(Stream Load 稳定在 120MB/s)
  • StarRocks:1 小时 52 分钟(Broker Load 达 145MB/s)
  • AnalyticDB MySQL:47 分钟(OSS 并行导入达 310MB/s)

实操心得:AnalyticDB 的 OSS 导入速度之所以快,是因为它绕过了传统 JDBC 的序列化开销,直接将 OSS 对象作为数据源,由计算节点本地解析 Parquet。我们曾尝试用 DataX 同步 Doris,耗时翻倍,且失败率高达 18%。

3.3 压测脚本与 SQL 模板:17 条 SQL 的真实业务映射

我们拒绝使用合成 SQL,所有 17 条模板均来自过去三个月线上慢查询日志 Top 20。以下是其中 5 条代表性 SQL 及其业务含义:

编号SQL 片段(简化)业务场景关键挑战
SQL-01SELECT region, COUNT(*) FROM fact_user_event JOIN dim_region ON ... WHERE event_date BETWEEN '2024-04-01' AND '2024-04-30' GROUP BY region全国各区域订单量日报大表 Join + 时间范围扫描,Doris 需手动建物化视图
SQL-02SELECT user_id, COUNT(*) OVER (PARTITION BY user_id ORDER BY event_time ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) FROM fact_user_event WHERE event_date = '2024-04-15'用户 7 日活跃度滚动计算窗口函数 + 高频时间排序,StarRocks 在该 SQL 上 P95 延迟达 1.8s
SQL-03SELECT COUNT(DISTINCT user_id) FROM fact_user_event WHERE event_type IN ('click','pay') AND event_date >= '2024-04-01'核心行为用户去重统计高基数 DISTINCT,Doris 默认 Bitmap 效果差,需改用 ApproxCountDistinct
SQL-04SELECT p.category, AVG(f.price) FROM fact_user_event f JOIN dim_product p ON f.product_id = p.id WHERE f.event_date = '2024-04-15' GROUP BY p.category HAVING COUNT(*) > 1000商品类目均价分析(带过滤)多表 Join + HAVING 过滤,AnalyticDB 自动将 HAVING 下推至 Join 前
SQL-05WITH recent AS (SELECT * FROM fact_user_event WHERE event_date >= '2024-04-10'), top_users AS (SELECT user_id FROM recent GROUP BY user_id ORDER BY COUNT(*) DESC LIMIT 1000) SELECT u.user_id, COUNT(*) FROM recent r JOIN top_users u ON r.user_id = u.user_id GROUP BY u.user_idTOP N 用户行为深度分析CTE 递归 + 大结果集 Join,Doris CTE 优化较弱,常触发 spill to disk

压测脚本使用 Python + Locust 框架编写,核心逻辑如下:

# locustfile.py from locust import HttpUser, task, between import random import time SQL_TEMPLATES = [ "SELECT region, COUNT(*) FROM fact_user_event f JOIN dim_region d ON f.region_id = d.id WHERE f.event_date BETWEEN %s AND %s GROUP BY region", "SELECT user_id, COUNT(*) OVER (PARTITION BY user_id ORDER BY event_time ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) FROM fact_user_event WHERE event_date = %s", # ... 其余 15 条 ] class AnalyticDBUser(HttpUser): wait_time = between(0.1, 0.5) # 模拟真实用户间隔 @task def execute_sql(self): sql_idx = random.randint(0, len(SQL_TEMPLATES)-1) sql = SQL_TEMPLATES[sql_idx] # 动态填充日期参数,模拟真实时间范围 if sql_idx == 0: start_date = "2024-04-01" end_date = "2024-04-30" params = (start_date, end_date) elif sql_idx == 1: date = "2024-04-15" params = (date,) # ... 其他参数填充 # 发送 HTTP 请求(AnalyticDB 使用 REST API) with self.client.post( "/api/v1/sql", json={"sql": sql % params, "database": "ads_db"}, name=f"SQL-{sql_idx+1}", catch_response=True ) as response: if response.status_code != 200: response.failure(f"HTTP {response.status_code}") else: try: result = response.json() if result.get("code") != 200: response.failure(f"SQL Error: {result.get('message', 'unknown')}") except: response.failure("Invalid JSON response")

注意:Doris 和 StarRocks 使用 MySQL 协议直连,AnalyticDB 则调用其开放的 REST API(更贴近真实业务调用链路)。我们特意没用 JDBC,就是为了规避驱动层差异带来的干扰。

3.4 关键参数调优:不是“调参”,而是“释放引擎原生能力”

很多团队以为 Benchmark 就是疯狂调参。实际上,我们只做了三处必要调整,且全部基于官方最佳实践:

  • Doris:

    • exec_mem_limit=8589934592(8GB):防止大查询 OOM,但设太高会导致内存争抢;
    • parallel_fragment_exec_level=4:提升多核利用率,但超过 4 后收益递减;
    • disable_stream_preaggregation=false:开启流式预聚合,对 COUNT DISTINCT 类查询提速明显。
  • StarRocks:

    • query_timeout_s=300:延长超时时间,避免毛刺期误判;
    • mem_limit=10737418240(10GB):与 Doris 保持一致;
    • enable_global_runtime_filter=true:开启全局运行时过滤,对 Join 性能提升显著。
  • AnalyticDB MySQL:

    • ob_query_timeout=300:同 StarRocks;
    • ob_enable_parallel_dml=true:启用并行 DML,对大批量 INSERT/UPDATE 加速;
    • 唯一特殊配置:ob_use_plan_cache=true(默认开启),这是 AnalyticDB 的“隐形加速器”——它会自动缓存执行计划,相同 SQL 模板的第二次执行,跳过 Parser 和 Optimizer 阶段,直接复用计划。我们压测中发现,SQL-01 的第二次执行耗时比首次低 63%,而 Doris 和 StarRocks 每次都要重新生成执行计划。

实操心得:别迷信“调参大全”。我们曾把 Doris 的batch_size从 1024 调到 8192,结果 P95 延迟反而升高 11%,因为大 batch 增加了单次处理的锁持有时间。真正的调优,是理解每个参数背后的资源博弈逻辑。

4. 压测结果深度分析:17 条 SQL 的逐条对比与根因诊断

4.1 综合性能对比:P95 延迟与资源利用率双维度

我们以最严苛的“毛刺期 P95 延迟”为黄金指标(单位:毫秒),并同步记录毛刺期间的 CPU 平均利用率(%)。结果如下表所示(仅展示前 10 条,完整 17 条见附录):

SQL 编号业务类型Doris P95Doris CPU%StarRocks P95StarRocks CPU%AnalyticDB P95AnalyticDB CPU%AnalyticDB 领先幅度
SQL-01区域聚合124092.398085.758061.2比 Doris 快 53.2%,CPU 低 31.1%
SQL-02窗口计算182088.6112079.462064.8比 StarRocks 快 44.6%,CPU 低 14.6%
SQL-03高基数去重215095.1198091.249058.3比 Doris 快 77.2%,CPU 低 36.8%
SQL-04类目均价143087.4132083.656060.1比 Doris 快 60.8%,CPU 低 27.3%
SQL-05TOP N 分析320096.8285094.571066.7比 Doris 快 77.8%,CPU 低 30.1%
SQL-06多维交叉分析265093.2241089.768062.4比 Doris 快 74.3%,CPU 低 30.8%
SQL-07实时漏斗转化198089.5176085.359059.2比 Doris 快 70.2%,CPU 低 30.3%
SQL-08用户分群画像285094.7252091.872063.5比 Doris 快 74.7%,CPU 低 31.2%
SQL-09商品关联推荐312095.9278093.475065.1比 Doris 快 76.0%,CPU 低 30.8%
SQL-10实时库存预警132086.4118082.753057.9比 Doris 快 59.8%,CPU 低 28.5%

关键结论:

  • AnalyticDB 在全部 17 条 SQL 中,P95 延迟均值为642ms,Doris 为2280ms,StarRocks 为1920ms,AnalyticDB 领先 Doris71.8%,领先 StarRocks66.5%;
  • CPU 利用率方面,AnalyticDB 均值62.5%,Doris92.1%,StarRocks88.3%,意味着 AnalyticDB 用不到 Doris 70% 的计算资源,就完成了同等负载;
  • 更重要的是稳定性:Doris 在 SQL-05(TOP N 分析)上出现 3.2% 的超时失败,StarRocks 在 SQL-02(窗口计算)上失败率 1.8%,AnalyticDB 全程 0 失败。

4.2 典型 SQL 深度根因分析:为什么 AnalyticDB 能“无感”加速?

我们选取 SQL-03(高基数去重)和 SQL-05(TOP N 分析)做深度剖析,因为这两条最能体现架构差异。

SQL-03 根因分析:COUNT(DISTINCT user_id)

  • Doris 行为:默认使用 Bitmap 精确去重,但user_id是 16 位 UUID,Bitmap 内存占用爆炸。我们观察到 BE 节点内存中bitmap_column占用达 12GB,触发频繁 GC,最终降级为ApproxCountDistinct(近似去重),误差率 0.8%,且 P95 延迟飙升;
  • StarRocks 行为:同样使用 Bitmap,但其内存管理更激进,当 Bitmap 内存超限时,自动切换为HyperLogLog(HLL)算法,误差率 1.2%,P95 延迟略低但精度损失更大;
  • AnalyticDB 行为:采用Roaring Bitmap + SIMD 指令加速。它将user_id的 16 字节哈希值拆分为 4 个 4 字节整数,每个整数用独立的 Roaring Bitmap 管理,再通过 AVX2 指令并行计算交集。内存占用仅 3.2GB,且全程无 GC 压力。执行计划显示,COUNT(DISTINCT)算子耗时仅 87ms,占总耗时 17.8%。

SQL-05 根因分析:CTE 递归 + 大结果集 Join

  • Doris 行为:CTErecent被物化为临时表,top_users的 1000 行结果也物化,但 Join 时 Doris 的 Hash Join 算子未对top_users做 Broadcast 优化(因其大小超过阈值),转而使用 Shuffle Join,导致大量网络传输和磁盘 Spill;
  • StarRocks 行为:同样未 Broadcast,但其 Shuffle 优化更好,Spill 量比 Doris 少 40%,P95 延迟低 12%;
  • AnalyticDB 行为:优化器识别出top_users结果集仅 1000 行,自动将其 Broadcast 到所有计算节点,Join 变成本地内存 Hash Join,网络传输量为 0。执行计划中,Broadcast算子明确标注broadcast_rows=1000,且Hash Join耗时仅 42ms。

提示:AnalyticDB 的 Broadcast 优化不是固定阈值,而是基于实时内存水位和网络带宽预测动态决策。我们曾手动关闭ob_broadcast_join参数,SQL-05 的 P95 延迟立刻升至 1280ms,证明这不是“参数红利”,而是引擎的自主判断能力。

4.3 资源监控对比:不只是“快”,更是“稳”和“省”

我们截取毛刺期(第 30-31 分钟)的监控快照,对比三套系统的健康度:

监控维度DorisStarRocksAnalyticDB MySQL说明
CPU 平均利用率94.7%91.2%63.5%Doris 多个 BE 节点 CPU 持续 100%,出现任务积压
磁盘 IO 等待队列1389224Doris 的 IO Wait 高,因频繁 Spill to Disk
网络出口带宽2.1 Gbps1.8 Gbps0.7 GbpsAnalyticDB 计算存储分离,计算节点间通信少
JVM GC 频次(Doris/StarRocks)12 次/分钟8 次/分钟—AnalyticDB 无 JVM,C++ 内存管理更稳定
查询排队数47220Doris FE 节点成为瓶颈,新查询排队等待

这张表揭示了一个残酷现实:自建方案的“性能”是透支系统健康换来的。Doris 的 94.7% CPU 利用率,背后是 138 的 IO 队列和 47 的查询排队,这已经不是“高性能”,而是“濒临崩溃”。而 AnalyticDB 的 63.5% CPU,配合 24 的 IO 队列和 0 排队,意味着它还有 36.5% 的余量可以应对下一次毛刺——这才是企业级数仓该有的样子。

5. 常见问题与实战避坑指南:那些文档里不会写的血泪教训

5.1 “为什么我的 AnalyticDB 没这么快?”——5 个高频误区排查

我们收到最多的问题是:“我们试了 AnalyticDB,但没你们说的那么快”。经过 12 个客户案例复盘,90% 的问题集中在以下 5 个误区:

  1. 误区一:用 MySQL 客户端直连,没走 REST API
    很多团队习惯用 Navicat 或 DBeaver 连 AnalyticDB,这会触发完整的 MySQL 协议握手和字符集协商,增加 150-200ms 固定开销。正确做法:业务应用层直接调用 REST API(官方 SDK 已支持 Java/Python/Go),或使用 AnalyticDB 提供的专用 JDBC Driver(mysql-connector-java-8.0.33+analyticdb-mysql-jdbc-1.0.0.jar),它会自动启用协议压缩和连接池优化。

  2. 误区二:索引建在“感觉重要”的字段上,而非查询模式上
    我们见过客户在user_id上建了唯一索引,但所有 SQL 都是WHERE event_date = ? AND product_id = ?。正确做法:用 AnalyticDB 的EXPLAIN FORMAT=TRADITIONAL查看执行计划,重点关注key_len和rows字段。如果key_len显示只用了索引前 2 列,而你的 WHERE 条件有 3 列,说明索引设计不合理。我们建议:联合索引的第一列,必须是查询中=条件出现频率最高的字段。

  3. 误区三:盲目开启并行查询,导致小查询变慢
    ob_enable_parallel_dml=true对大批量 INSERT 极有效,但对单条SELECT COUNT(*)这类轻量查询,开启并行反而增加调度开销。正确做法:AnalyticDB 支持 SQL Hint 控制并行度,如SELECT /*+ PARALLEL(4) */ COUNT(*) FROM t。我们压测发现,对 < 100ms 的查询,并行度设为 1 最优;对 100ms-1s 查询,设为 4;> 1s 查询,设为 8。

  4. 误区四:忽略统计信息更新,让优化器“瞎猜”
    AnalyticDB 的优化器极度依赖统计信息。我们曾遇到客户表数据量从 1 亿涨到 5 亿,但没更新统计信息,导致优化器误判 Join 顺序,P95 延迟从 400ms 暴涨到 2800ms。正确做法:每天凌晨业务低峰期,执行ANALYZE TABLE table_name;。对于超大表,可用采样:ANALYZE TABLE table_name SAMPLE_RATE 0.1;(采样 10%)。

  5. 误区五:把 AnalyticDB 当 Doris 用,硬扛高并发点查
    AnalyticDB 是 OLAP 引擎,不是 OLTP 数据库。我们见过客户用它支撑 5000 QPS 的用户资料点查,结果 P95 延迟 1200ms。正确做法:点查类需求,用 Redis 或 PolarDB 做前置缓存;AnalyticDB 专注复杂分析。它的优势在于:1 个 AnalyticDB 实例,能同时支撑 200 个并发的复杂分析查询,而 Doris 可能需要 5 个节点才能做到。

5.2 自建方案迁移实操 checklist:从 Doris 到 AnalyticDB 的平滑过渡

如果你正考虑迁移,这份 checklist 是我们帮 7 家客户落地的经验结晶:

  1. 第一步:Schema 兼容性扫描
    使用 AnalyticDB 提供的adb-schema-compat-tool,输入 Doris 的建表 DDL,它会输出:
    • ✅ 完全兼容字段(如BIGINT,VARCHAR,DATE)
    • ⚠️ 需转换字段(如 Doris 的DECIMAL(10,2)→ Analytic
返回列表