经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Oracle » 查看文章
测试merge效率
来源:cnblogs  作者:皇家救星  时间:2019/5/15 9:10:34  对本文有异议

测试说明:

MERGE是oracle提供的一种特殊的sql语法,非常适用于数据同步场景,即: (把A表数据插到B表,如果B表存在相同主键的记录则使用A表数据对B表进行更新) 数据同步的常规做法是先尝试插入,插入失败再进行更新,MERGE比这种常规做法效率高很多。 (特别是A与B表基本一致,同步时主键冲突比较多的情况,效率能相差10倍以上)

为了验证MERGE效率,我建了两张表,tab_test_C(初始化生成50000条记录)和tab_test_Q(初始化从tab_test_C生成40000条记录), 写了两个plsql脚本,分别将tab_test_C的数据同步到tab_test_Q,看它们效率区别。

第一个脚本使用merge语法,第二个脚本使用常规先插入,出现主键冲突的操作。


测试结果:
 使用merge语法的脚本同步数据耗时0.04秒,使用常规操作耗时14.77秒,效率差369倍

 

测试脚本:

  1. SET SERVEROUTPUT ON
  2. -- 启动计时 以便观察脚本执行时间
  3. SET TIMING ON
  4. SET TIME ON
  1. -- 数据初始化
  2. DROP TABLE tab_test_C;
  3. CREATE TABLE tab_test_C
  4. (
  5. C1 VARCHAR2(512),
  6. C2 VARCHAR2(512),
  7. C3 VARCHAR2(512),
  8. C4 VARCHAR2(512),
  9. C5 VARCHAR2(512),
  10. C6 VARCHAR2(512),
  11. C7 VARCHAR2(512),
  12. C8 VARCHAR2(512),
  13. C9 VARCHAR2(512),
  14. C10 VARCHAR2(512)
  15. );
  16. DECLARE
  17. v_total number;
  18. BEGIN
  19. v_total := 0;
  20. LOOP
  21. EXIT WHEN v_total >= 50000;
  22. for cur in (select owner, object_name, subobject_name, object_id, data_object_id, object_type,
  23. created, last_ddl_time, timestamp from all_objects where rownum < 101)
  24. loop
  25. insert into tab_test_C values (cur.owner, cur.object_name, cur.subobject_name,
  26. cur.object_id, cur.data_object_id,
  27. cur.object_type, cur.created,
  28. cur.last_ddl_time, cur.timestamp, v_total);
  29. v_total := v_total + 1;
  30. end loop;
  31. END LOOP;
  32. COMMIT;
  33. END;
  34. /
  35.  
  36. -- 建唯一索引
  37. select count(1) from tab_test_C;
  38. create UNIQUE INDEX uid_test_c_1 on tab_test_C(C10);
  1. --初始化tab_test_Q表数据,先从tab_test_C生成同步40000条数据,剩下10000条数据使用脚本同步过来
  2. DROP TABLE tab_test_Q;
  3. CREATE TABLE tab_test_Q AS SELECT * FROM tab_test_C where rownum < 40001;
  4. create UNIQUE INDEX uid_test_q_1 on tab_test_Q(C10);
  5. -- 验证数据未同步成功 此时记录数差1000
  6. select count(*) from tab_test_Q;
  1. -- 使用merge语法同步tab_test_C的数据到tab_test_Q
  2. DECLARE
  3. CURSOR cur is select * from tab_test_C;
  4. type mergeArray_t is table of tab_test_C % ROWTYPE index by BINARY_INTEGER;
  5. mergeArray mergeArray_t;
  6. BEGIN
  7. OPEN cur;
  8. LOOP
  9. EXIT WHEN cur % NOTFOUND;
  10. FETCH cur bulk collect into mergeArray LIMIT 16; -- 每次限十几条记录,不要占用太多内存 这个数字调大点效率会更高
  11. BEGIN
  12. FORALL rw IN 1 .. mergeArray.count
  13. MERGE INTO tab_test_Q A
  14. USING (SELECT mergeArray(rw).C1 C1, mergeArray(rw).C2 C2, mergeArray(rw).C3 C3, mergeArray(rw).C4 C4,
  15. mergeArray(rw).C5 C5, mergeArray(rw).C6 C6, mergeArray(rw).C7 C7, mergeArray(rw).C8 C8,
  16. mergeArray(rw).C9 C9, mergeArray(rw).C10 C10 FROM DUAL) B
  17. ON (A.C10 = B.C10)
  18. WHEN MATCHED THEN
  19. UPDATE SET A.C1 = mergeArray(rw).C1, A.C2 = mergeArray(rw).C2, A.C3 = mergeArray(rw).C3,
  20. A.C4 = mergeArray(rw).C4, A.C5 = mergeArray(rw).C5,
  21. A.C6 = mergeArray(rw).C6, A.C7 = mergeArray(rw).C7, A.C8 = mergeArray(rw).C8,
  22. A.C9 = mergeArray(rw).C9
  23. WHEN NOT MATCHED THEN
  24. INSERT (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) VALUES(mergeArray(rw).C1, mergeArray(rw).C2,
  25. mergeArray(rw).C3, mergeArray(rw).C4, mergeArray(rw).C5, mergeArray(rw).C6,
  26. mergeArray(rw).C7, mergeArray(rw).C8, mergeArray(rw).C9, mergeArray(rw).C10);
  27. -- DBMS_OUTPUT.PUT_LINE(mergeArray.count);
  28. EXCEPTION
  29. WHEN OTHERS THEN
  30. DBMS_OUTPUT.PUT_LINE('error1');
  31. END;
  32. END LOOP;
  33. CLOSE cur;
  34. COMMIT;
  35. END;
  36. /
  1. --耗时0.04
  2. -- 验证数据同步成功
  3. select count(*) from tab_test_Q;
  1. --初始化tab_test_Q表数据,先从tab_test_C生成同步40000条数据,剩下10000条数据使用脚本同步过来
  2. DROP TABLE tab_test_Q;
  3. CREATE TABLE tab_test_Q AS SELECT * FROM tab_test_C where rownum < 40001;
  4. create UNIQUE INDEX uid_test_q_1 on tab_test_Q(C10);
  5. -- 验证数据未同步成功 此时记录数差1000
  6. select count(*) from tab_test_Q;
  1. -- 使用常规语法同步tab_test_C的数据到tab_test_Q
  2. BEGIN
  3. for cur in (select * from tab_test_C)
  4. LOOP
  5. BEGIN
  6. INSERT INTO tab_test_Q(C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)
  7. VALUES(cur.C1, cur.C2, cur.C3, cur.C4, cur.C5, cur.C6, cur.C7, cur.C8, cur.C9, cur.C10);
  8. EXCEPTION
  9. WHEN DUP_VAL_ON_INDEX THEN --唯一索引冲突时更新
  10. UPDATE tab_test_Q SET C1 = cur.C1, C2 = cur.C2, C3 = cur.C3, C4 = cur.C4, C5 = cur.C5, C6 = cur.C6, C7 = cur.C7, C8 = cur.C8, C9 = cur.C9
  11. WHERE C10 = cur.C10;
  12. WHEN OTHERS THEN
  13. DBMS_OUTPUT.PUT_LINE('error1');
  14. END;
  15. END LOOP;
  16. COMMIT;
  17. END;
  18. /
  1. --耗时14.77
  2. -- 验证数据同步成功
  3. select count(*) from tab_test_Q;

 

原文链接:http://www.cnblogs.com/kingstarer/p/10865941.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号