zoukankan      html  css  js  c++  java
  • oracle update from多表性能优化一例

    这几天测试java内存数据库,和oracle比较时发下一个update from语句很慢,如下:

    update business_new
               set fare1_balance_ratio = (select BALANCE_RATIO             from bfare2
                       where bfare2.exchange_type = business_new.exchange_type and
                             bfare2.stock_type = business_new.stock_type and
                             (bfare2.entrust_way = business_new.entrust_way) and
                             (bfare2.entrust_type = business_new.entrust_type) 
            and bfare2.fare_type = '0')

    执行计划是这样的:

    从执行计划可以看出,走的就是nl关联,所以慢是正常的。

    于是将其改写为merge,如下:

    merge into business_new using bfare2
    on (bfare2.exchange_type = business_new.exchange_type and
                             bfare2.stock_type = business_new.stock_type and
                             (bfare2.entrust_way = business_new.entrust_way) and
                             (bfare2.entrust_type = business_new.entrust_type) 
            and bfare2.fare_type = '4')
            when matched then update
               set business_new.farex_balance_ratio = bfare2.BALANCE_RATIO

    改写后执行计划如下:

    很快就跑出来了。需要注意的是,update语句本身是通过hint让两表强制走hash join的。

    除了用merge改写让两表关联走hash join外,还有一种更优、但有条件的做法。如下:

    update (select fare1_balance_ratio,BALANCE_RATIO from business_new,bfare2
     where bfare2.exchange_type = business_new.exchange_type and
                             bfare2.stock_type = business_new.stock_type and
                             (bfare2.entrust_way = business_new.entrust_way) and
                             (bfare2.entrust_type = business_new.entrust_type) 
            and bfare2.fare_type = '0')
               set fare1_balance_ratio = BALANCE_RATIO ;

    这也称为inline view更新法,性能是最好的,但相比merge并不明显。但表B的主键一定要在where条件中,并且是以“=”来关联被更新表,否则会遇到ORA-01779: 无法修改与非键值保存表对应的列。造成这个错误的原因是更新的列不是事实表的列,而是维度表的列。换句话说,如果两张表关联,其中一张表的关联列是主键,那么另一张表就是事实表,也就是说另一张表中的列就是可更新的;除非另一张表的关联列也是主键,否则这张表就是不可更新的,如果更新语句涉及到了这张表,就会出现ORA-1799错误。也就是,要么两张表都通过PK关联,要么只有非PK这张表可更新。

    至于for循环,乖乖,除非逻辑特别复杂,用for bulk collect,否则不要考虑。

  • 相关阅读:
    使用Publish Over SSH插件实现远程自动部署
    Certificates does not conform to algorithm constraints
    在 Linux 命令行脚本中执行 sudo 时自动输入密码
    pig学习
    Attention-based Model
    kesci---2019大数据挑战赛预选赛---情感分析
    计算广告(1)---广告技术概览
    Hadoop 使用小命令(2)
    shell学习(2)----常用语法
    docker入门
  • 原文地址:https://www.cnblogs.com/zhjh256/p/11173252.html
Copyright © 2011-2022 走看看