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。

相关推荐
kingx31 小时前
Windows Server 2008 应急加固实战:7 项入侵痕迹排查与修复
数据库·windows·提权·应急响应·加固
xiaogai_gai1 小时前
采购业务退款单同步实战:从钉钉审批流到金蝶云星空付款单
java·数据库·钉钉
AlickLbc2 小时前
DM-V8数据库证书过期处理过程记录
数据库
l1t2 小时前
DeepSeek总结的五分钟测试:Ted Dunning 谈 DuckDB 为何让分析更轻松
数据库·sql·duckdb
超级新零售2 小时前
零售 SaaS 与本地部署,技术责任边界究竟怎么分?
数据库·零售
考虑考虑2 小时前
瀚高数据库
数据库·后端·postgresql
dishugj3 小时前
oracle日志切换三条命令区别
数据库
Patrick在香港3 小时前
一个斜杠,把毫秒变成十几秒
android·数据库·python·性能优化·正则表达式·回溯·redos
悟道书生3 小时前
(一)Navicate为什么转存结构和数据只转存表而不包含建库?
数据库·oracle
赤龙ERP4 小时前
ERP周报:连接器开闸、国产GPU进场与智能工厂253家
数据库·人工智能·大模型·rpa·erp·企业数字化·builderpattern