oracle update from多表性能優化一例

這幾天測試java內存數據庫,和oracle比較時發下一個update from語句很慢,以下:java

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關聯,因此慢是正常的。oracle

因而將其改寫爲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的。spa

除了用merge改寫讓兩表關聯走hash join外,還有一種更優、但有條件的作法。以下:code

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這張表可更新。blog

至於for循環,乖乖,除非邏輯特別複雜,用for bulk collect,不然不要考慮。內存

相關文章
相關標籤/搜索