row_number()函数与group by性能比较

1、 问题

最近项目中发现row_number()函数去重写法性能会比group by性能稍微差一些,原语句如下:

bash 复制代码
SELECT 
        COUNT(1)
FROM
        (
        WITH
                ORG AS
                (
                        SELECT
                                *
                        FROM
                                (
                                        SELECT
                                                group_code,
                                                group_name,
                                                ROW_NUMBER() OVER(PARTITION BY group_code ORDER BY NULL) RN
                                        FROM
                                                ORG_BASIS
                                       
                                        union all
                                        
                                        select
                                                '09' as group_code,
                                                group_name       ,
                                                ROW_NUMBER() OVER(PARTITION BY group_code ORDER BY NULL) RN
                                        from
                                                ORG_BASIS
                                        where
                                                group_code = '0900'
                                        
                                )
                        WHERE
                                RN = 1
                )
                
        select
                o1.group_name as pName,                                                                                                                                                           
                o2.group_name as bName  ,                                                                                                                                                           
                t1.BUREAU_CODE                                                             
        FROM
                TRAN_PLAN t1
        LEFT JOIN ORG o1
        ON
                t1.province_code = o1.group_code
        LEFT JOIN ORG o2
        ON
                t1.BUREAU_CODE = o2.group_code
                
        WHERE
                t1.PLAN_NATURE     = 1
            AND t1.POWER_GRID_FLAG = 1
            AND t1.SPECIALITY     IN (11, 12, 13)
                
            AND t1.PLAN_END_TIME  < DATEADD(YEAR, 1, TO_DATE(?, 'yyyy-mm-dd'))
            AND t1.PLAN_END_TIME >= TO_DATE(?, 'yyyy-mm-dd')
                
            AND T1.PROVINCE_CODE = ?
                
            AND T1.BUREAU_CODE = ?
                
            AND
                (
                        t1.PLAN_STATE IN (50, 60, 70, 110)
                )
                
        )
        t;

计划:

单次执行性能是正常的,但一定的压力下,热点就在窗口函数,压测情况如下:

这里平均值达5s左右。

row_number() 是一种 SQL 窗口函数,常用于对分组数据进行排序并生成唯一的行号。大白话就是排序去重。

语句中是对group_code分组生成序号取第一个。group_name和group_code是一一对应的,那么对这两列进行分组就可以满足需求。因此可以用group by替换改写。

2、改写

bash 复制代码
SELECT 
        COUNT(1)
FROM
        (
        WITH
                ORG AS
                (
                        SELECT
                                *
                        FROM
                                (
                                        SELECT
                                                group_code,
                                                max(group_name) group_name
                                       FROM
                                                ORG_BASIS
                                       
                                       group by group_code
                                        union all
                                        
                                        select
                                                '09' as group_code,
                                                max(group_name) group_name       
                                        from
                                                ORG_BASIS
                                        where
                                                group_code = '0900'
                                        group by group_code
                                        
                                )
                      
                )
                
        select
               
                o1.group_name as pName,                                                                                                                                                          
                o2.group_name as buName  ,                                                                                                                                                          
                t1.bureau_code                                                           
        FROM
                TRAN_PLAN t1
        LEFT JOIN ORG o1
        ON
                t1.province_code = o1.group_code
        LEFT JOIN ORG o2
        ON
                t1.BUREAU_CODE = o2.group_code
                
        WHERE
                t1.PLAN_NATURE     = 1
            AND t1.POWER_GRID_FLAG = 1
            AND t1.SPECIALITY     IN (11, 12, 13)
                
            AND t1.PLAN_END_TIME  < DATEADD(YEAR, 1, TO_DATE(?, 'yyyy-mm-dd'))
            AND t1.PLAN_END_TIME >= TO_DATE(?, 'yyyy-mm-dd')
                
            AND T1.PROVINCE_CODE = ?
                
            AND T1.BUREAU_CODE = ?
                
            AND
                (
                        t1.PLAN_STATE IN (50, 60, 70, 110)
                )
                
        )
        t;

计划:

压测情况

性能比较稳定。

3、小结

Row_number()函数会内部进行排序,因此比group by多了排序内存消耗,所以总的来说,能用group by替换row_number()做去重就选择group by。

相关推荐
naturliche9 分钟前
sgx支持数据库环境配置,编译,debug
数据库·编译·sgx
SelectDB19 分钟前
Apache Doris x Fluss:面向湖流一体的统一查询与分析
大数据·数据库·数据分析
云贝贝贝20 分钟前
Oracle 备份恢复实战:RMAN 备份、恢复与误删闪回
数据库
java1234_小锋21 分钟前
【技术专题】Mysql8 数据库 - Mysql8 触发器
数据库·mysql·mysql8
要吃这碗饭29 分钟前
AI 智能体如何通过 auth.md 注册 Bright Data 账号
数据库·人工智能·php
薛晓刚35 分钟前
Oracle ADG 备库归档丢了怎么办?RMAN 增量前滚实战
数据库·oracle
Highcharts.js40 分钟前
用Highcharts开发动态主从图表|双图联动的时间序列图表示例
javascript·数据库·信息可视化·highcharts·图表开发·动态图表
阿俊-全栈开发43 分钟前
LikeShop 版本升级与备份:从旧版平滑迁移的完整步骤
jvm·数据库·oracle·开源·likeshop·likeshop开源商城
姜鱼问生2 小时前
docker exec 排查容器问题:从日志到进程
运维·网络·数据库·docker·容器
狗凯之家源码网2 小时前
AI 步数修改提交系统源码应用场景与落地指南
android·数据库·人工智能·运动步数