General principles: 1) The where condition must be added when updating, otherwise it will inevitably cause all records in the field to be updated
2) When updating across tables, when set and where, try to reduce the number of scans to improve optimization
update update instance:
1 ) Simplest form - single table update
- --It is confirmed that all customer_id less than 1000 in the customers table are 'Beijing'
- --Those less than 1000 are the old customers in the city before the company went to the whole country :)
- update customers
- set city_name= 'Beijing'
- where customer_id<1000
2 ) Two-table (multi-table) association update -- set is simple data (direct value), and only the connection in the where clause
- --The data extracted this time are all VIPs, including new ones, so update the customer category by the way
- update customers a -- use an alias
- set customer_type= '01' --01 is vip, 00 is ordinary
- where exists (select 1
- from tmp_cust_city b
- where b.customer_id=a.customer_id
- )
3 ) Two-table (multi-table) associated update -- the modified value is calculated from another table
- update customers a -- use an alias
- set city_name=(select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id)
- where exists (select 1
- from tmp_cust_city b
- where b.customer_id=a.customer_id
- )
- Optimization: Optimization of a single field, simplified to scan once
7.1 SQL code
- update customers a -- use an alias
- set city_name=nvl((select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id),a.city_name)
- --update more than 2 values (fields )
- update customers a -- use an alias
- set (city_name,customer_type)=(select b.city_name,b.customer_type
- from tmp_cust_city b
- where b.customer_id=a.customer_id)
- where exists (select 1
- from tmp_cust_city b
- where b.customer_id=a.customer_id
- )
3的缺点,就是对表B进行两遍扫描;
4) 特殊情况的优化:
因为B表的纪录只有A表的20-30%的纪录数,且
A表使用INDEX的情况
使用cursor也许会比关联update带来更好的性能:
- set serveroutput on
- declare
- cursor city_cur is
- select customer_id,city_name
- from tmp_cust_city
- order by customer_id;
- begin
- for my_cur in city_cur loop
- update customers
- set city_name=my_cur.city_name
- where customer_id=my_cur.customer_id;
- /** 此处也可以单条/分批次提交,避免锁表情况 **/
- -- if mod(city_cur%rowcount,10000)=0 then
- -- dbms_output.put_line('----');
- -- commit;
- -- end if;
- end loop;
- end;
5) 关联update的一个特例以及性能再探讨
在Oracle的update语句语法中,除了可以update表之外,也可以是视图,所以有以下1个特例:
- update (select a.city_name,b.city_name as new_name
- from customers a,
- tmp_cust_city b
- where b.customer_id=a.customer_id
- )
- set city_name=new_name
这样能避免对B表或其索引的2次扫描,但前提是 A(customer_id) b(customer_id)必需是unique index或primary key