這幾天測試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,不然不要考慮。內存