upsert VS merge
来源:互联网 发布:javascript 按位取反 编辑:程序博客网 时间:2024/06/01 07:21
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:6618304976523
ops$tkyte@ORA920.US.ORACLE.COM> create global temporary table ao 2 on commit PRESERVE ROWS 3 as 4 select * 5 from all_objects 6 where 1=0;Table created.ops$tkyte@ORA920.US.ORACLE.COM> alter table ao 2 add constraint 3 ao_pk primary key(object_id);Table altered.ops$tkyte@ORA920.US.ORACLE.COM> insert into ao select * from all_objects;29311 rows created.ops$tkyte@ORA920.US.ORACLE.COM> create table t1 2 as 3 select * 4 from all_objects 5 where rownum<= (select count(*)/2 from all_objects);Table created.ops$tkyte@ORA920.US.ORACLE.COM> alter table t1 add constraint t1_pk primary key(object_id);Table altered.ops$tkyte@ORA920.US.ORACLE.COM> analyze table t1 compute statistics 2 for table for all indexes for all indexed columns;Table analyzed.ops$tkyte@ORA920.US.ORACLE.COM> create table t2 2 as 3 select * 4 from all_objects 5 where rownum<= (select count(*)/2 from all_objects);Table created.ops$tkyte@ORA920.US.ORACLE.COM> alter table t2 add constraint t2_pk primary key(object_id);Table altered.ops$tkyte@ORA920.US.ORACLE.COM> analyze table t2 compute statistics 2 for table for all indexes for all indexed columns;Table analyzed.So, t1 and t2 are for all intents and purposes the same -- we'll upsert them from AO..ops$tkyte@ORA920.US.ORACLE.COM> declare 2 l_start number; 3 l_run1 number; 4 l_run2 number; 5 6 type rc is ref cursor; 7 l_cur rc; 8 begin 9 insert into run_stats select 'before', stats.* from stats; 10 11 l_start := dbms_utility.get_time; 12 merge into t1 13 using ao on ( t1.object_id = ao.object_id ) 14 when matched then 15 update set owner = ao.owner, 16 object_name = ao.object_name, 17 subobject_name = ao.subobject_name, 18 data_object_id = ao.data_object_id, 19 object_type = ao.object_type, 20 created = ao.created, 21 last_ddl_time = ao.last_ddl_time, 22 timestamp = ao.timestamp, 23 status = ao.status, temporary = ao.temporary, 24 generated = ao.generated, 25 secondary = ao.secondary 26 when not matched then 27 insert ( OWNER, OBJECT_NAME, 28 SUBOBJECT_NAME, OBJECT_ID, 29 DATA_OBJECT_ID, OBJECT_TYPE, 30 CREATED, LAST_DDL_TIME, 31 TIMESTAMP, STATUS, TEMPORARY, 32 GENERATED, SECONDARY ) 33 values ( ao.OWNER, ao.OBJECT_NAME, 34 ao.SUBOBJECT_NAME, ao.OBJECT_ID, 35 ao.DATA_OBJECT_ID, ao.OBJECT_TYPE, 36 ao.CREATED, ao.LAST_DDL_TIME, 37 ao.TIMESTAMP, ao.STATUS, ao.TEMPORARY, 38 ao.GENERATED, ao.SECONDARY); 39 commit; 40 l_run1 := (dbms_utility.get_time-l_start); 41 dbms_output.put_line( l_run1 || ' hsecs' ); 42 43 insert into run_stats select 'after 1', stats.* from stats; 44 l_start := dbms_utility.get_time; 45 for x in ( select * from ao ) 46 loop 47 update t2 set ROW = x where object_id = x.object_id; 48 if ( sql%rowcount = 0 ) 49 then 50 insert into t2 values X; 51 end if; 52 end loop; 53 commit; 54 l_run2 := (dbms_utility.get_time-l_start); 55 dbms_output.put_line( l_run2 || ' hsecs' ); 56 dbms_output.put_line 57 ( 'run 1 ran in ' || round(l_run1/l_run2*100,2) || '% of the time' ); 58 59 insert into run_stats select 'after 2', stats.* from stats; 60 end; 61 /424 hsecs2116 hsecsrun 1 ran in 20.04% of the timePL/SQL procedure successfully completed.merge is faster wallclock wise then procedural code and...ops$tkyte@ORA920.US.ORACLE.COM> select a.name, b.value-a.value run1, c.value-b.value run2, 2 ( (c.value-b.value)-(b.value-a.value)) diff 3 from run_stats a, run_stats b, run_stats c 4 where a.name = b.name 5 and b.name = c.name 6 and a.runid = 'before' 7 and b.runid = 'after 1' 8 and c.runid = 'after 2' 9 and (c.value-a.value) > 0 10 and (c.value-b.value) <> (b.value-a.value) 11 order by abs( (c.value-b.value)-(b.value-a.value)) 12 /NAME RUN1 RUN2 DIFF------------------------------ ---------- ---------- ----------...STAT...redo entries 30661 45670 15009LATCH.redo allocation 30780 46012 15232STAT...db block gets 47239 62630 15391STAT...table scan blocks gotte 597 29311 28714nSTAT...buffer is not pinned co 693 29409 28716untSTAT...index fetch by key 9 29320 29311STAT...db block changes 60912 90825 29913STAT...no work - consistent re 260 36398 36138ad getsSTAT...calls to get snapshot s 450 44200 43750cn: kcmgssSTAT...execute count 63 44015 43952LATCH.shared pool 463 44606 44143STAT...consistent gets - exami 729 51860 51131nationSTAT...recursive calls 838 73844 73006STAT...consistent gets 1748 88444 86696LATCH.library cache pin 436 88558 88122LATCH.library cache 757 89093 88336STAT...session pga memory 95732 0 -95732STAT...session logical reads 48987 151074 102087LATCH.cache buffers chains 212197 405774 193577STAT...session pga memory max 947700 0 -947700STAT...redo size 12908776 16933156 4024380100 rows selected.ops$tkyte@ORA920.US.ORACLE.COM>it did less work -- generated 75% of the redo and so on...Now, I ran that as a pipelined function (two merges -- merge vs merge) and the results were that the merge using a TABLE bested the pipelined function with about the same ratios. ...ops$tkyte@ORA920.US.ORACLE.COM> create type myScalarType as object ( 2 OWNER VARCHAR2(30), 3 OBJECT_NAME VARCHAR2(30), 4 SUBOBJECT_NAME VARCHAR2(30), 5 OBJECT_ID NUMBER, 6 DATA_OBJECT_ID NUMBER, 7 OBJECT_TYPE VARCHAR2(18), 8 CREATED DATE, 9 LAST_DDL_TIME DATE, 10 TIMESTAMP VARCHAR2(19), 11 STATUS VARCHAR2(7), 12 TEMPORARY VARCHAR2(1), 13 GENERATED VARCHAR2(1), 14 SECONDARY VARCHAR2(1) 15 ) 16 /Type created.ops$tkyte@ORA920.US.ORACLE.COM> create type myArrayType as table of myScalarType 2 /Type created.ops$tkyte@ORA920.US.ORACLE.COM>ops$tkyte@ORA920.US.ORACLE.COM> create or replace function ao_function return myArrayType 2 PIPELINED 3 as 4 begin 5 for ao in (select * from all_objects) 6 loop 7 pipe row( myScalarType( ao.OWNER, ao.OBJECT_NAME, 8 ao.SUBOBJECT_NAME, ao.OBJECT_ID, 9 ao.DATA_OBJECT_ID, ao.OBJECT_TYPE, 10 ao.CREATED, ao.LAST_DDL_TIME, 11 ao.TIMESTAMP, ao.STATUS, ao.TEMPORARY, 12 ao.GENERATED, ao.SECONDARY) ); 13 end loop; 14 return; 15 end; 16 /Function created.....ops$tkyte@ORA920.US.ORACLE.COM> declare 2 l_start number; 3 l_run1 number; 4 l_run2 number; 5 6 type rc is ref cursor; 7 l_cur rc; 8 begin 9 insert into run_stats select 'before', stats.* from stats; 10 11 l_start := dbms_utility.get_time; 12 merge into t1 13 using ao on ( t1.object_id = ao.object_id ) 14 when matched then 15 update set owner = ao.owner, 16 object_name = ao.object_name, 17 subobject_name = ao.subobject_name, 18 data_object_id = ao.data_object_id, 19 object_type = ao.object_type, 20 created = ao.created, 21 last_ddl_time = ao.last_ddl_time, 22 timestamp = ao.timestamp, 23 status = ao.status, temporary = ao.temporary, 24 generated = ao.generated, 25 secondary = ao.secondary 26 when not matched then 27 insert ( OWNER, OBJECT_NAME, 28 SUBOBJECT_NAME, OBJECT_ID, 29 DATA_OBJECT_ID, OBJECT_TYPE, 30 CREATED, LAST_DDL_TIME, 31 TIMESTAMP, STATUS, TEMPORARY, 32 GENERATED, SECONDARY ) 33 values ( ao.OWNER, ao.OBJECT_NAME, 34 ao.SUBOBJECT_NAME, ao.OBJECT_ID, 35 ao.DATA_OBJECT_ID, ao.OBJECT_TYPE, 36 ao.CREATED, ao.LAST_DDL_TIME, 37 ao.TIMESTAMP, ao.STATUS, ao.TEMPORARY, 38 ao.GENERATED, ao.SECONDARY); 39 commit; 40 l_run1 := (dbms_utility.get_time-l_start); 41 dbms_output.put_line( l_run1 || ' hsecs' ); 42 43 insert into run_stats select 'after 1', stats.* from stats; 44 l_start := dbms_utility.get_time; 45 merge into t2 46 using (select * from TABLE(ao_function)) ao on ( t2.object_id = ao.object_id ) 47 when matched then 48 update set owner = ao.owner, 49 object_name = ao.object_name, 50 subobject_name = ao.subobject_name, 51 data_object_id = ao.data_object_id, 52 object_type = ao.object_type, 53 created = ao.created, 54 last_ddl_time = ao.last_ddl_time, 55 timestamp = ao.timestamp, 56 status = ao.status, temporary = ao.temporary, 57 generated = ao.generated, 58 secondary = ao.secondary 59 when not matched then 60 insert ( OWNER, OBJECT_NAME, 61 SUBOBJECT_NAME, OBJECT_ID, 62 DATA_OBJECT_ID, OBJECT_TYPE, 63 CREATED, LAST_DDL_TIME, 64 TIMESTAMP, STATUS, TEMPORARY, 65 GENERATED, SECONDARY ) 66 values ( ao.OWNER, ao.OBJECT_NAME, 67 ao.SUBOBJECT_NAME, ao.OBJECT_ID, 68 ao.DATA_OBJECT_ID, ao.OBJECT_TYPE, 69 ao.CREATED, ao.LAST_DDL_TIME, 70 ao.TIMESTAMP, ao.STATUS, ao.TEMPORARY, 71 ao.GENERATED, ao.SECONDARY); 72 commit; 73 l_run2 := (dbms_utility.get_time-l_start); 74 dbms_output.put_line( l_run2 || ' hsecs' ); 75 dbms_output.put_line 76 ( 'run 1 ran in ' || round(l_run1/l_run2*100,2) || '% of the time' ); 77 78 insert into run_stats select 'after 2', stats.* from stats; 79 end; 80 /494 hsecs1737 hsecsrun 1 ran in 28.44% of the timePL/SQL procedure successfully completed. ops$tkyte@ORA920.US.ORACLE.COM> select a.name, b.value-a.value run1, c.value-b.value run2, 2 ( (c.value-b.value)-(b.value-a.value)) diff 3 from run_stats a, run_stats b, run_stats c 4 where a.name = b.name 5 and b.name = c.name 6 and a.runid = 'before' 7 and b.runid = 'after 1' 8 and c.runid = 'after 2' 9 and (c.value-a.value) > 0 10 and (c.value-b.value) <> (b.value-a.value) 11 order by abs( (c.value-b.value)-(b.value-a.value)) 12 /....STAT...session pga memory 104256 232480 128224STAT...session uga memory 0 130928 130928STAT...session uga memory max 0 130928 130928LATCH.row cache enqueue latch 362 177614 177252LATCH.row cache objects 448 184995 184547LATCH.cache buffers chains 211442 493338 281896STAT...session pga memory max 956224 166944 -789280STAT...redo size 12876460 14459964 1583504106 rows selected. It is the removal of the procedural, handwritten code here that makes the difference. We should strive for ways to do things SET ORIENTED (as sql likes that best). The less procedural code we write in general the better.
- upsert VS merge
- Upsert
- merge sort vs. quicksort
- git: Rebase vs Merge
- PostgreSQL upsert
- pymongo upsert
- git merge vs rebase vs cherry-pick
- git merge vs rebase vs cherry-pick
- git merge vs rebase vs cherry-pick
- merge VS rebase VS cherry-pick
- git merge vs rebase vs cherry-pick
- git: fetch vs pull, merge vs rebase
- hash join VS merge join
- git merge vs git rebase
- git rebase vs git merge
- no_merge/merge vs no_unnest/unnest
- Quick sort VS Merge sort
- git pull vs fetch/rebase/merge
- 一场校园选举的“意外”争议
- 二叉树
- MD5破解
- 关于浮点数在计算机中的储存
- ADT20与SDK兼容问题
- upsert VS merge
- 9AnonymousInnerClass(匿名内部类)是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?
- 把virtual box的鏡像轉成qemu的鏡像
- 关于hadoop中datanode节点不同的dfs.data.dir之间数据均衡问题
- MySQL索引背后的数据结构及算法原理
- How the Cloud Is Changing Security
- Power基于 VIOS 的虚拟以太网适配器的工作原理
- 简明vim练级攻略
- 如何给wordpress添加显示文章阅读数的功能