ITPub博客

首页 > 数据库 > 数据库开发技术 > 基于达梦的SQL等价改写优化案例精选第一部【一统天下】②分析函数的穿透之力

基于达梦的SQL等价改写优化案例精选第一部【一统天下】②分析函数的穿透之力

原创 数据库开发技术 作者:梁敬彬 时间:2025-05-19 06:30:46 0 删除 编辑


往期回顾

  SQL等价改写优化案例精选第一部【一统天下】① count(case when)的合并魔力


在SQL优化中,分析函数(Analytics Functions)是一类功能强大但常被忽视的工具。它们能在单次数据扫描中完成复杂的计算,避免多次访问相同数据。本案例将展示如何利用KEEP和DENSE_RANK函数组合,将多次表扫描简化为一次,大幅提升查询性能。

在这里插入图片描述

案例2:KEEP与DENSE_RANK的完美配合

在前一篇案例中,我们对一个复杂SQL进行了全面优化。今天,我们聚焦其中的一个关键环节:如何优化获取每个peer_id最新状态的子查询。

原始SQL:嵌套子查询的性能陷阱

select distinct dsl1.peer_id peer_id,
                                 nvl(ne_disconnect_info.ne_state, 1) ne_state
                   from dcc_sys_log dsl1,
                        (select distinct dnl.peer_id peer_id,
                                         decode(action,
                                                'disconnect',
                                                0,
                                                'connect',
                                                0,
                                                1) ne_state
                           from dcc_sys_log dsl, dcc_ne_log dnl
                          where dsl.peer_id = dnl.peer_id
                            and ((dsl.action = 'disconnect' and
                                dsl.cause = '关闭对端') or
                                (dsl.action = 'connect' and
                                dsl.cause = '连接主机失败'))
                            and log_type = '对端交互'
                            and dsl.log_time =
                                (select max(log_time)
                                   from dcc_sys_log
                                  where peer_id = dnl.peer_id
                                    and log_type = '对端交互')) ne_disconnect_info
                  where dsl1.peer_id = ne_disconnect_info.peer_id(+)


问题分析:

 1. 复杂的嵌套子查询结构

 2. 内部子查询需要多次访问dcc_sys_log表

 3. 每个peer_id都要执行相关子查询,找出最大log_time

 4. 连接逻辑复杂,可读性差

优化方案:分析函数的巧妙应用

原先至少需要扫描2次!现在根据KEEP结合DENSE_RANK的方式,将表扫描从2次变为了1次,具体代码改写如下:

SELECT 
    a.peer_id,
    CASE 
        WHEN dnl.peer_id IS NOT NULL 
             AND str IN ('disconnect关闭对端', 'connect连接主机失败') 
        THEN '0' 
        ELSE '1' 
    END ne_state
FROM 
    (
        SELECT 
            peer_id,
            MIN(action||cause) KEEP(DENSE_RANK LAST ORDER BY log_time) str 
        FROM 
            dcc_sys_log dsl
        WHERE 
            log_type = '对端交互'
        GROUP BY 
            peer_id
    ) a,
    (
        SELECT 
            DISTINCT peer_id 
        FROM 
            dcc_ne_log
    ) dnl 
WHERE 
    a.peer_id = dnl.peer_id(+)


优化解析:KEEP函数的魔力

这个优化方案使用了Oracle特有的KEEP...DENSE_RANK组合,这是一种强大但常被忽视的分析工具。让我们深入理解它的工作原理:

1. 分析函数如何改变游戏规则

原始SQL中,我们需要:

 1. 先按peer_id分组

 2. 对每组找出最大log_time的记录

 3. 再检查该记录的action和cause组合是否满足条件

传统方式需要使用嵌套子查询,至少扫描表两次。但使用KEEP函数,我们可以在单次扫描中完成同样的工作。

2. KEEP(DENSE_RANK...)的工作机制

MIN(action||cause) KEEP(DENSE_RANK LAST ORDER BY log_time)


这行代码的含义是:

 1. 按log_time排序(DENSE_RANK ORDER BY log_time)

 2. 取排序后的最后一条记录(LAST)

 3. 返回该记录的action||cause值

一句话完成了原先需要嵌套子查询才能实现的功能!

结语

分析函数是SQL优化的强大武器,它可以将多次数据访问简化为一次,大幅提升查询性能。在面对需要查询"最新"、"最大"、"排名前N"等场景时,优先考虑使用分析函数,而不是复杂的嵌套子查询。

正如本案例所示,通过KEEP和DENSE_RANK的组合,我们将原本需要两次表扫描的复杂查询简化为一次扫描,不仅提高了性能,还增强了代码的可读性和可维护性。这正是SQL等价改写的艺术所在。


未完待续...

  SQL等价改写优化案例精选第一部【一统天下】③ group by (case when)的聚合艺术

公众号:收获不止数据库

微信:ljbyxl1213

系列回顾


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9091385/viewspace-3084631/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
历任中电福富研究院副理事长、中盾安信研究院副院长、宁德时代技术顾问等职务,受聘电信集团专家和国家十四五课题负责人,著有《收获,不止Oracle》《收获,不止SQL优化》等多本畅销数据库技术书籍。

注册时间:2024-02-06

  • 博文量
    162
  • 访问量
    198127