注册
SQL 解析慢的根因定位与优化方向
专栏/技术分享/ 文章详情 /

SQL 解析慢的根因定位与优化方向

Gyyyyy 2026/10/23 54 0 0
摘要

达梦 SQL 优化:SQL 解析慢的根因定位与优化方向

导读:一条 SQL 执行 18 秒,可真正「跑」数据只花了约 3 秒,剩下 15 秒全耗在解析(含优化)阶段。很多人的第一反应是「加索引」「调执行计划」,方向全错了。本文还原这类「解析慢」场景的定位过程:如何用 V$SQL_STAT 发现解析占比、如何识别「视图互引」这个真正的元凶、以及「去冗余 → 改写法 → 参数 hint」三层递进的优化手段。


一、问题背景:执行 18 秒,解析占 15 秒

生产上一条 SQL 执行耗时 18 秒,分析后发现大部分时间花在了 SQL 解析阶段,而不是执行阶段。

怎么发现的?查 V$SQL_STAT:

-- 查出 exec_time(执行时长)与 parse_time(解析时长)的占比 SELECT * FROM sys.v$sql_stat WHERE sql_txt LIKE '%UPDATE%';

结果清晰:exec_time 约 18 秒,其中 parse_time 就占了 15 秒多。瓶颈在解析,不在执行。

二、根因:关联的表和视图过多,查询树成倍展开

回到 SQL 文本,看到 FROM 关键字后有三张主表,还关联了多个 _v1 视图。进一步查看这些视图的 DDL 定义,发现视图的定义里还关联了其他视图。

这就是问题所在:视图层层嵌套、互相引用,导致优化器要展开的查询树成倍膨胀,解析/优化阶段的代价随之飙升。

达梦的解析优化能力其实很强——纯物理表多(几十张)、长 UNION ALL、CTE、ROWNUM 视图等,解析都在几十毫秒内。真正让解析爆炸的,是「同一批视图被反复 join(自互引)+ 每层再叠聚合/子查询」。

三、优化方向(三层递进)

3.1 第一层:去除冗余逻辑

  1. 去除冗余逻辑:SQL 解析时间很长时,先看有没有可以砍掉的无用逻辑;
  2. 去除冗余关联:有些内层字段外层根本没用到,与之关联的表就是冗余内连接,直接去掉;
  3. 减少视图互引:把 V1 JOIN V1 JOIN V2 JOIN V3... 的互引,改写为单次引用 + 提前物化中间结果(临时表 / CTE 引用一次)。

3.2 第二层:改写典型慢写法

这个 SQL 里有一个视图里写了 11 个 UNION ALL 分支,按业务逻辑可以改写为 DECODE:

  • 把 usage_detail_code 的 11 个等值条件合并成一个 IN;
  • 上方的 page_type 通过 DECODE 处理。

这既是「去掉冗余」的一部分,也是「减少视图复杂度」的手段(详见《视图内 11 个 UNION ALL 分支改 IN + DECODE》一文)。

3.3 第三层:参数 hint 应急

对这条 SQL 加了 MAX_OPT_N_TABLES 的 hint 后,执行时长从 18 秒下降到 2 秒左右:

SELECT /*+MAX_OPT_N_TABLES(4)*/ ...

这是通过优化参数加一个 hint 的临时应急解决办法。

MAX_OPT_N_TABLES 参数含义

MAX_OPT_N_TABLES 用于指定在处理连接时,一次能优化的最大表连接个数。如果待连接的表个数超过了 MAX_OPT_N_TABLES,则先将前 MAX_OPT_N_TABLES 个表作为一组进行探测优化,得到一个固定的连接顺序,将其视为一个整体 Ta,再将 Ta 与后续(MAX_OPT_N_TABLES - 1)个表进行探测优化,如此反复进行探测优化。

简单说:达梦默认 MAX_OPT_N_TABLES = 6,≤6 张表走穷举搜索最优连接顺序,>6 张转启发式。hint 调大它能让更多表参与穷举,有时能选到更优计划;但也会放大解析时间,需要权衡。

四、实测对照:解析开销的量化验证

在干净实例上构造同型场景实测,验证「解析时间」这一判断:

场景 EXPLAIN / 执行耗时
3 表 join 22 ms
6 表 join 73 ms
20 表 join 183 ms(转启发式,不再爆炸)
3 层聚合视图链(不可合并) 153 ms
6 个业务视图互相引用 + EXISTS + 大 IN EXPLAIN 270 ms / 执行 1.995 s
多视图互引 + 聚合链 + 大 IN(复现峰值) 7.064 s / 1.2 s

结论:纯表多不爆炸,视图互引才爆炸。把同一批视图反复 join(自互引)+ 每层带聚合/子查询,解析时间能稳定到秒级;生产 16 秒场景 = 视图互引数量 × 规模远超本模拟。

五、总结

  1. 先分清「解析慢」还是「执行慢」:查 V$SQL_STAT 的 parse_time 占比,方向错了全白费。
  2. 解析慢的充分条件:同一批视图互相引用多次(尤其含聚合/子查询的不可合并视图),查询树成倍展开。
  3. 优化核心三层递进:减少视图互引 → 关键视图打平/去冗余 → 参数 hint 权衡,可落地。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服