SQL中Union All语句优化改写经验分享
1、问题
前面几个案例是因为提前生成HEAP TABLE,条件没有提前过滤导致性能问题,今天想跟大家分享一个案例是适合做HEAP TABLE优化的。原语句如下:
SELECT *
FROM(SELECT INNER_TABLE.*,
ROWNUM OUTER_TABLE_ROWNUM
FROM (SELECT T1.CODE,
case when T1.CODE='-9999' then '合计'
else t2.cname end cname,
nvl(firstnum,0)firstnum,
nvl(secondnum,0)secondnum,
nvl(thirdnum,0)thirdnum,
nvl(fourthnum,0)fourthnum,
nvl(fifthnum,0)fifthnum
from ( select '-9999' code,
sum(case when status=1 then 1 else 0 end) firstnum,
sum(case when status=2 then 1 else 0 end) secondnum,
sum(case when status=3 then 1 else 0 end) thirdnum,
sum(case when status=4 then 1 else 0 end) fourthnum,
sum(case when status=5 then 1 else 0 end) fifthnum
from t1
where c1 like 'A1%'
union all
select code,
sum(case when status=1 then 1 else 0 end) firstnum,
sum(case when status=2 then 1 else 0 end) secondnum,
sum(case when status=3 then 1 else 0 end) thirdnum,
sum(case when status=4 then 1 else 0 end) fourthnum,
sum(case when status=5 then 1 else 0 end) fifthnum
from t1
where c1 like 'A1%'
group by code) t1 left join t2 on t1.code=t2.code
ORDER BY T1.CODE)INNER_TABLE ) OUTER_TABLE
WHERE OUTER_TABLE_ROWNUM<=200AND OUTER_TABLE_ROWNUM >0计划:

从计划上对t1表过滤重复两次,从语句中可以看到
select '-9999' code,
sum(case when status=1 then 1 else 0 end) firstnum,
sum(case when status=2 then 1 else 0 end) secondnum,
sum(case when status=3 then 1 else 0 end) thirdnum,
sum(case when status=4 then 1 else 0 end) fourthnum,
sum(case when status=5 then 1 else 0 end) fifthnum
from t1
where c1 like 'A1%'
union all
select code,
sum(case when status=1 then 1 else 0 end) firstnum,
sum(case when status=2 then 1 else 0 end) secondnum,
sum(case when status=3 then 1 else 0 end) thirdnum,
sum(case when status=4 then 1 else 0 end) fourthnum,
sum(case when status=5 then 1 else 0 end) fifthnum
from t1
where c1 like 'A1%'
group by code是union all两部分,一部分是合计,另一部分是分组统计,此时我想到可以先分组统计,再把分组统计结果进行合计,分组统计的结果可以放到临时表中即heap table,从数学角度上讲就是提取公因子。
2、改写
SELECT *
FROM(SELECT INNER_TABLE.*,
ROWNUM OUTER_TABLE_ROWNUM
FROM (SELECT T1.CODE,
case when T1.CODE='-9999' then '合计'
else t2.cname end cname,
nvl(firstnum,0)firstnum,
nvl(secondnum,0)secondnum,
nvl(thirdnum,0)thirdnum,
nvl(fourthnum,0)fourthnum,
nvl(fifthnum,0)fifthnum
from (with temp as (
select code,
sum(case when status=1 then 1 else 0 end) firstnum,
sum(case when status=2 then 1 else 0 end) secondnum,
sum(case when status=3 then 1 else 0 end) thirdnum,
sum(case when status=4 then 1 else 0 end) fourthnum,
sum(case when status=5 then 1 else 0 end) fifthnum
from t1
where c1 like 'A1%'
group by code)
select '-9999' code, sum(firstnum) firstnum,
sum(secondnum) secondnum, sum(thirdnum)thirdnum,
sum(fourthnum) fourthnum,sum(fifthnum) fifthnum
from temp t1
union all
select * from temp
) t1
left join t2 on t1.code=t2.code
ORDER BY T1.CODE)INNER_TABLE ) OUTER_TABLE
WHERE OUTER_TABLE_ROWNUM<=200AND OUTER_TABLE_ROWNUM >0计划:

结果符合预期,性能提升一倍以上。
3、小结
使用union all和group by rollup(前面案例中有提过-单表查询-group by rollup优化)进行数据统计的sql优化思路就是提取公因子,利用临时表(HEAP TABLE)减少扫描次数,从而提升性能。
前面讲过优化不是单向,前面是讲HEAP TABLE如何拆解优化,而这次是如何用HEAP TABLE减少扫描次数优化,优化做的事不过是对症下药。
4、附加测试数据
create table t1(id int primary key,c1 varchar2(20),status int,code varchar2(20)); insert into t1 select level,'A'||to_char(round(dbms_random.value(1,10000),0)),round(dbms_random.value(1,5),0), '0'||to_char(round(dbms_random.value(300,322),0)) from dual connect by level<=300000; commit; dbms_stats.gather_table_stats(USER,'T1',null,100); create table t2(id int primary key,cname varchar2(20),code varchar2(20)); insert into t2 select level,'A'||to_char(round(dbms_random.value(300,322),0)), '0'||to_char(round(dbms_random.value(300,322),0)) from dual connect by level<=10000; commit; dbms_stats.gather_table_stats(USER,'T2',null,100); create index IDX_DM_T1_C1 on T1(c1); create index IDX_DM_t2_CODE on T2(CODE);
到此这篇关于SQL中Union All语句优化改写经验分享的文章就介绍到这了,更多相关union all语句优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
- SQL中UNION与UNION ALL的区别小结
- MySQL中关键字UNION和UNION ALL的区别
- mysql的union和union all用法详解
- 简单聊一聊SQL中的union和union all
- mysql中union和union all的使用及注意事项
- MySQL系列理解运用union(all)与limit及exists关键字教程
- sql优化实战 把full join改为left join +union all(从5分钟降为10秒)
- 简单了解MySQL union all与union的区别
- MySQL如何使用union all获得并集排序
- MySQL中UNION与UNION ALL的基本使用方法
相关文章
MySQL中获取最大值MAX()函数和ORDER BY … LIMIT 1比较
mysql取最大值的的是max 和order by两种方式,同时也大多数人人为max的效率更高,在本文中,我们将介绍MySQL中MAX()和ORDER BY … LIMIT 1两种获取最大值的方法以及它们性能上的差异,同时我们将探讨这种性能差异的原因,并提供一些优化建议2024-03-03
详解MySQL中JSON数据类型用法及与传统JSON字符串对比
MySQL从 5.7 版本开始引入了 JSON 数据类型,专门用于存储 JSON 格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型用法并与传统JSON字符串对比,希望对大家有所帮助2025-07-07


最新评论