Coffee都喝了三杯,查询还在跑...别担心!老王这儿有本Doris加速秘笈
小王盯着终端里疯狂跳动的查询时间,内心不禁感叹:“为什么这条SQL像乌龟一样慢啊!”
多年后…老王想起自己刚接触Doris的时候。记得有一次,他信心满满地写了个看似简单的查询,结果等啊等,Coffee都喝了三杯,查询还在跑。那一刻,老王深刻体会到"slow query"带来的痛苦。
经过这些年的实战经验积累,老王发现查询调优其实就像是中医看病 - 望闻问切缺一不可。先要有好的"诊断工具"找出病因,然后对症下药,最后还要讲究调养之道。
今天就让我们跟着老王一起开启这段Doris查询调优之旅,带你从"查询等到头秃"升级到"查询快到飞起"!
![[tu]](https://i-blog.csdnimg.cn/direct/564aa902b5884956ae424fa58355f26c.png)
Doris调优秘笈概述
在数据库领域,查询性能一直是个热门话题。特别是对于Apache Doris这样的MPP数据库,一个SQL查询的执行可能会涉及几十个甚至上百个节点的协同工作。优化不当,查询性能就会大打折扣。
老王经常收到私信:“王儿,我们的查询太慢了,动不动就要跑几分钟,该怎么优化啊?”
说实话,这个问题没有标准答案。查询性能受多方面因素影响,需要我们从整体视角来分析和优化。
![[tu]](https://i-blog.csdnimg.cn/direct/df89c61d898d47c4ad20d4c2094457b6.png)
就像医生看病一样,优化查询也要讲究方法。首先要有一套好用的"诊断工具",快速定位到性能瓶颈。好在Doris为我们提供了两大利器:
Doris Manager监控
Doris Manager 监控提供了丰富的功能界面,用户可以方便地获取包括集群信息、硬件信息、Doris 版本信息等基础信息,以及 FE / BE 节点信息和 CPU / MEM / IO / NETWORK 等维度的实时监控信息。如下图所示:
![[tu]](https://i-blog.csdnimg.cn/direct/6c0b2d920805432fbe3d421d9919b3ca.png)
fe.audit.log日志分析
在性能监控方面,当前 Manager 提供了基于日志的慢 SQL 定位方式。用户可以通过选择特定 FE 节点上的fe.audit.log来查看慢 SQL。只需在搜索框中输入“slow_query”,即可在页面上展示出当前系统的历史慢 SQL 信息,如下图所示:
![[tu]](https://i-blog.csdnimg.cn/direct/b3d9b2d8e86c4d1cbb19c27d5499177f.png)
通过这两个工具,我们可以方便地发现慢查询,定位问题所在。
拿到慢查询后,就该"对症下药"了。Doris提供了丰富的优化工具,包括查看执行计划的Explain、分析运行状态的Profile等。通过这些工具,我们能清晰地看到查询是如何执行的,哪里出现了性能瓶颈。
举个栗子:
老王曾经遇到过一个查询,明明只需要查最近一天的数据,执行计划却显示扫描了全表。通过Explain发现,优化器没有下推分区过滤条件。调整表的分区设计后,查询时间从原来的5分钟降到了5秒。
-- 分区设计后的销售数据表 sales
CREATE TABLE sales (
date DATE,
product VARCHAR(50),
amount DECIMAL(10, 2)
)
PARTITION BY RANGE(date) (
PARTITION p1 VALUES LESS THAN ('2023-01-01'),
PARTITION p2 VALUES LESS THAN ('2023-02-01'),
PARTITION p3 VALUES LESS THAN ('2023-03-01'),
PARTITION p4 VALUES LESS THAN ('2023-04-01')
)
DISTRIBUTED BY HASH(date) BUCKETS 16
PROPERTIES
(
"replication_num" = "1"
);
-- 查询SQL
SELECT SUM(amount) AS total_amount
FROM sales
WHERE date BETWEEN '2023-01-15' AND '2023-02-15';
对于上述查询,Doris 的分区裁剪优化过程如下:
-
Doris 智能分析查询条件中的分区列 date,识别出查询的日期范围在 ‘2023-01-15’ 到 ‘2023-02-15’ 之间。
-
通过比较查询条件与分区定义,Doris 精确定位需要扫描的分区范围。在本例中,只需要扫描分区 p2 和 p3,因为这两个分区的日期范围完全覆盖了查询条件。
-
Doris 自动跳过与查询条件无关的分区,如 p1 和 p4,避免了不必要的数据扫描,从而减少了 I/O 开销。
-
最后,Doris 仅在分区 p2 和 p3 中执行数据扫描和聚合计算,快速获取查询结果。
通过如下 EXPLAIN 命令,我们可以查看查询执行计划,确认 Doris 的分区裁剪优化已生效。在执行计划中,OlapScanNode 节点的 partition 属性将显示实际扫描的分区为 p2 和 p3。
| 0:VOlapScanNode(212) |
| TABLE: cir.sales(sales), PREAGGREGATION: ON |
| PREDICATES: (date[#0] >= '2023-01-15') AND (date[#0] <= '2023-02-15') |
| partitions=2/4 (p2,p3) | |
这就引出了Doris查询加速秘笈的核心调优方法论:
![[tu]](https://i-blog.csdnimg.cn/direct/e370e24bb2914ace8c402514f79dd9f2.png)
1. 使用性能诊断工具进行慢查询定位
针对运行在 Doris 上的业务系统,使用上述性能诊断工具进行 慢 SQL 的定位。
-
如果已经安装了 Doris Manager,推荐使用 Manager 的监控和日志页面,进行可视化的慢查询定位。
-
如果没有安装 Manager,可以直接查看 FE 节点上的 fe.audit.log来获取。针对筛选出的慢 SQL 列表,逐一按照优先级和严重程度进行 SQL 级别的调优。
2. Schema 设计与调优
定位到具体的慢 SQL 之后,优先需要对业务 Schema 设计进行检查与调优,排除因为 Schema 设计不合理导致的性能问题。
Schema 设计调优基本可分为三个方面:
-
表级别 Schema 设计调优,如分区分桶个数和字段调优;
-
索引的设计和调优;
-
特定优化手段的使用,如建立 Colocate Group 等。主要目的是排除因为 Schema 设计不合理或者没有充分利用 Doris 现有优化能力导致的性能问题
3. 计划调优
检查和优化完业务 Schema 后,将进入调优的主体工作,即计划调优与执行调优。如上所述,在性能调优工具中,这个阶段的主要工作是充分利用 Doris 所提供的各种层级的 Explain 工具,对慢 SQL 的执行计划进行系统分析,以找到关键优化点进行针对性优化。
-
针对单表查询和分析场景,可以通过分析执行计划、查看分区裁剪是否正常、是否可以构建单表物化视图进行查询加速等。
-
针对复杂多表分析场景,可以分析统计信息是否正常、分析 Join Order 是否合理、分析 Runtime Filter 是否正常规划等,定位具体的性能瓶颈。如果出现非预期的情况,比如 Join Order 不合理,通过观察 Explain 的结果、手工指定 Join Jint 进行执行计划的绑定、控制 Join 顺序和 Shuffle 方式、控制代价改写行为等操作方法,从而达到调优执行计划的目的。
-
针对部分特定场景,可以通过使用 Doris 提供的高级功能,比如异步物化视图改写、SQL Cache 等来加速查询。
4. 执行调优
在这个阶段,我们需要根据 SQL 的实际运行情况,来验证前几步的调优效果是否显著,或者发现慢 SQL 的新瓶颈点。接着,我们可以按图索骥,找到对应的性能优化方案。
以多表分析的查询为例,我们可以通过分析 Query Profile,来检查 Join 的顺序是否合理,Runtime Filter 是否生效,以及等待时间是否合适。很多时候,执行时的调优更多是为了佐证之前的 Schema 和计划调优是否符合预期。
此外,Query Profile 还能反馈出一些 BE 或机器负载的情况,例如 CPU 占用高、网络卡顿等运行状态问题。在针对这些问题进行调优时,我们需要跳出 Doris 本身,进行操作系统级别的调优。
But,在实际工作中,老王发现很多开发者一上来就想调优执行计划,却忽视了Schema和索引优化。这好比是一个运动员,不注重基本功练习,一味追求高难度动作,最终往往事倍功半…
Doris加速秘笈序幕
老王眨眨眼,一脸神秘地说:“先别急着合上’秘笈’往外冲。不过呢,光抱着这本’秘笈’发呆也不是办法。这让我想起以前遇到个有趣的场景 - 一位同学在家啃了一个月的MySQL调优文档,自信满满地说’我已经是调优高手啦’。结果真正上手优化的时候,却像个初学跳舞的人,光记住了动作要领,但一到舞池就手忙脚乱。”
老王轻啜一口Coffee,继续说道:“所以啊,咱们得像厨师学做菜那样 - 看完菜谱,就得卷起袖子,亲自下厨试试。可能第一次炒糊了,第二次太咸了,但只有在这反复尝试中,才能真正掌握火候。调优也一样,需要在实战中摸爬滚打,才能练就一双火眼金睛,看到SQL就知道病灶在哪。现在,一起’入厨’看看?”
案例一:Schema 设计的"蝴蝶效应"
![[tu]](https://i-blog.csdnimg.cn/direct/ac405d944b2c45aa9eb86cfac921dfd1.png)
有天,小李一脸愁容地找到老王:“王哥,我们的订单查询怎么这么慢啊,明明就查最近一周的数据,却要跑好几分钟!”
老王笑道:“让我们来看看你的表结构。”
CREATE TABLE orders (
order_id BIGINT,
user_id BIGINT,
status VARCHAR(32),
create_time DATETIME
) ...
"啊哈!"老王眼睛一亮,“这就像是把重要的客人安排在后排座位一样不合适。create_time 是查询的主力军,应该放在第一排!”
改造后的表结构:
CREATE TABLE orders (
create_time DATETIME,
order_id BIGINT,
user_id BIGINT,
status VARCHAR(32)
) ...
“这样一改,Doris的ZoneMap和前缀索引就能直接过滤掉不需要的数据块,查询速度蹭蹭往上涨!”
案例二:物化视图的"及时雨"
![[tu]](https://i-blog.csdnimg.cn/direct/261480921be742bb8a1881f8973aea1f.png)
一位数据分析师抱怨道:“每天统计各个商品的销售数据,都要跑半个小时,我的Coffee都喝了三杯了…”
老王眉头一挑:“这就像是每次吃饭都现磨大米一样,太浪费时间了。咱们可以用物化视图来’存米下锅’!”
-- 创建按天预计算的物化视图
CREATE MATERIALIZED VIEW product_daily_stats AS
SELECT
dt,
product_id,
COUNT(*) as orders,
SUM(amount) as total_amount
FROM orders
GROUP BY dt, product_id;
“这下好了,查询直接读取现成的统计结果,速度提升了 50 倍!就像是把米饭提前煮好,想吃随时就能吃。”
案例三:Runtime Filter 的"火眼金睛"
![[tu]](https://i-blog.csdnimg.cn/direct/2559dd29bf8f49b7a37ac0dc07d6fed0.png)
还有个有趣的案例,是关于订单和用户表关联查询的。查询需要找出所有 VIP 用户的订单,但是 VIP 用户只占总用户的 1%。
SELECT o.*
FROM orders o JOIN users u
ON o.user_id = u.id
WHERE u.is_vip = true;
老王解释道:“如果不用 Runtime Filter,就像是先把所有订单都找出来,再一个个问’这是 VIP 的订单吗?'。开启 Runtime Filter 后,就像是先拿到 VIP 用户清单,然后直接去找这些用户的订单,省去了大量无谓的数据读取。”
案例四:Join 顺序的"蝶恋花"
![[tu]](https://i-blog.csdnimg.cn/direct/cf64b1f9823d4fd18b1bf6a6f51b8403.png)
最逗的是一个处理五表关联的案例。原本的查询像是"群魔乱舞",执行计划看得人头晕。
老王打趣道:“Join 顺序不对,就像是跳广场舞找舞伴,要是步骤错了,跳到最后发现不是原来的搭档可就尴尬了。”
使用 Leading Hint 来指定正确的 Join 顺序:
SELECT /*+ LEADING(orders {users products}) */
o.order_id,
u.name,
p.product_name
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id;
“这就像是排练好的舞蹈动作,每一步都准确无误,性能自然就上去了!”
…
![[tu]](https://i-blog.csdnimg.cn/direct/bde475e0ec4d4af08cabd9bf2a85d142.png)
最后,老王深吸一口,在秘笈特别标注让大家记住一点:优化是个迭代过程。通过不断收集执行信息、分析瓶颈、验证优化效果,才能找到最佳方案。
关于老王的Doris加速秘笈就分享到这里。正所谓:“工欲善其事,必先利其器”,每个数据库场景都有其特点,希望这些经验能给大家一些启发。
欢迎在评论区分享你的优化经验。下期,我们将一起探讨其它更有趣有用有价值的内容,敬请期待!

9778






