文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SQL优化案例-使用with as优化Subquery Unnesting(七)

2024-04-02 19:55

关注

使用 no_unnest hint可以让执行计划产生filter,即不展开,但一般情况下使用unnest hint无法消除filter。

如下SQL,找出库中非唯一索引,那么大家可能会这么写SQL:


SELECT SEGMENT_NAME,SUM(BYTES/1024/1024) m FROM DBA_SEGMENTS WHERE SEGMENT_NAME 
NOT IN (select index_name from dba_indexes where UNIQUENESS ='NONUNIQUE') GROUP BY SEGMENT_NAME;

耗时一分钟,为什么这么慢呢?在SQL语句where子查询后有not in、not exists、in、exists时,CBO会尝试将子查询展开(unnest)消除filter,但是上面的例子CBO并没有做到,下面我们看下执行计划。

SQL优化案例-使用with as优化Subquery Unnesting(七)

我们再看下在子查询中加unnest hint的执行计划:


SELECT SEGMENT_NAME,SUM(BYTES/1024/1024) m FROM DBA_SEGMENTS WHERE
SEGMENT_NAME  NOT IN (select index_name from dba_indexes
where UNIQUENESS ='NONUNIQUE') GROUP BY SEGMENT_NAME;

SQL优化案例-使用with as优化Subquery Unnesting(七)

filter消除,CBO将基于数据字典底层的基表重新组合,使执行计划变成hash joinanti,0.23秒便执行完成了。

下面我们再来看下通过with as materialize优化subquery unnesting的例子。

SQL如下:


select  AREA_NAME,sum(reve)
from t_order o 
where exists (select AREA_ID
        from t_customer c
       where nation = 'Aus'
         and c.AREA_ID = o.AREA_ID
      union
      select AREA_ID
        from f_customer f 
      where nation = 'US'
        and f.AREA_ID <> o.f_area_id) group by AREA_NAME;

selectsum(bytes/1024/1024) M from dba_segments where segment_name ='F_CUSTOMER';
    M
----------
    192

表F_CUSTOMER192M

SQL优化案例-使用with as优化Subquery Unnesting(七)

执行计划如下:

SQL优化案例-使用with as优化Subquery Unnesting(七)

我们看到并不走索引,要近2个小时执行完成,通过建立组合索引,让其走index_ffs


CREATE INDEX IDX_FFS_NATION_ID ONf_customer(AREA_ID,nation,0);

SQL优化案例-使用with as优化Subquery Unnesting(七)

8分钟执行完成,那么还有没有更好的办法呢?

如下:


with x as ( select  AREA_ID from f_customer f 
      where nation = 'US') 
select  AREA_NAME,sum(reve)
from t_order o 
where exists (select AREA_ID
        from t_customer c
       where nation = 'Aus'
         and c.AREA_ID = o.AREA_ID
      union
      select AREA_ID
        from x where x.AREA_ID <> o.f_area_id) group by AREA_NAME;

SQL优化案例-使用with as优化Subquery Unnesting(七)

在FILTER中,NOT IN(NOT EXISTS)后的SQL语句多次执行,本来数据量就很大,每次都要执行一遍,结果可想而知。但是使用HINT MATERIALIZE和WITH AS 结合使用,把表中部分列实体化,执行过程中会创建基于视图的临时表。这样就不会每次NOT EXISTS都去执行一遍大数据表的扫描或者大的索引快速扫描,并且当表的数据越大,表越宽,这样的优化效果越明显。


|  作者简介

姚崇·沃趣科技高级数据库技术专家

熟悉Oracle、MySQL数据库内部机制,丰富的Oracle、MySQL故障诊断、性能调优、数据库备份恢复、复制、高可用方案及迁移经验。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯