測試merge效率

来源:https://www.cnblogs.com/kingstarer/archive/2019/05/15/10865941.html
-Advertisement-
Play Games

測試說明: MERGE是oracle提供的一種特殊的sql語法,非常適用於數據同步場景,即: (把A表數據插到B表,如果B表存在相同主鍵的記錄則使用A表數據對B表進行更新) 數據同步的常規做法是先嘗試插入,插入失敗再進行更新,MERGE比這種常規做法效率高很多。 (特別是A與B表基本一致,同步時主鍵 ...


測試說明:

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倍

 

測試腳本:

SET SERVEROUTPUT ON
-- 啟動計時 以便觀察腳本執行時間
SET TIMING ON
SET TIME ON
-- 數據初始化 
DROP TABLE tab_test_C;
CREATE TABLE tab_test_C 
(
    C1 VARCHAR2(512),
    C2 VARCHAR2(512),
    C3 VARCHAR2(512),
    C4 VARCHAR2(512),
    C5 VARCHAR2(512),
    C6 VARCHAR2(512),
    C7 VARCHAR2(512),
    C8 VARCHAR2(512),
    C9 VARCHAR2(512),
    C10 VARCHAR2(512)
);

DECLARE
    v_total number;
BEGIN
    v_total := 0;
    LOOP
        EXIT WHEN v_total >= 50000;
        for cur in (select owner, object_name, subobject_name, object_id, data_object_id, object_type, 
            created, last_ddl_time, timestamp from all_objects where rownum < 101)
        loop
            insert into tab_test_C values (cur.owner, cur.object_name, cur.subobject_name, 
            cur.object_id, cur.data_object_id, 
            cur.object_type, cur.created, 
            cur.last_ddl_time, cur.timestamp, v_total);
            v_total := v_total + 1;
        end loop;
    END LOOP;
    COMMIT;
END;
/

-- 建唯一索引
select count(1) from tab_test_C;
create UNIQUE INDEX uid_test_c_1 on tab_test_C(C10);
--初始化tab_test_Q表數據,先從tab_test_C生成同步40000條數據,剩下10000條數據使用腳本同步過來
DROP TABLE tab_test_Q;
CREATE TABLE tab_test_Q AS SELECT * FROM tab_test_C where rownum < 40001;
create UNIQUE INDEX uid_test_q_1 on tab_test_Q(C10);
-- 驗證數據未同步成功 此時記錄數差1000
select count(*) from tab_test_Q;
-- 使用merge語法同步tab_test_C的數據到tab_test_Q
DECLARE
    CURSOR cur is select * from tab_test_C;
    type mergeArray_t is table of tab_test_C % ROWTYPE index by BINARY_INTEGER;
    mergeArray mergeArray_t;
BEGIN
    OPEN cur;
    LOOP
        EXIT WHEN cur % NOTFOUND;
        FETCH cur bulk collect into mergeArray LIMIT 16; -- 每次限十幾條記錄,不要占用太多記憶體 這個數字調大點效率會更高
        BEGIN
            FORALL rw IN 1 .. mergeArray.count
                MERGE INTO tab_test_Q A
                USING (SELECT mergeArray(rw).C1 C1, mergeArray(rw).C2 C2, mergeArray(rw).C3 C3, mergeArray(rw).C4 C4, 
                    mergeArray(rw).C5 C5, mergeArray(rw).C6 C6, mergeArray(rw).C7 C7, mergeArray(rw).C8 C8, 
                    mergeArray(rw).C9 C9, mergeArray(rw).C10 C10 FROM DUAL) B
                ON (A.C10 = B.C10)
                WHEN MATCHED THEN
                    UPDATE SET A.C1 = mergeArray(rw).C1, A.C2 = mergeArray(rw).C2, A.C3 = mergeArray(rw).C3, 
                        A.C4 = mergeArray(rw).C4, A.C5 = mergeArray(rw).C5, 
                        A.C6 = mergeArray(rw).C6, A.C7 = mergeArray(rw).C7, A.C8 = mergeArray(rw).C8, 
                        A.C9 = mergeArray(rw).C9
                WHEN NOT MATCHED THEN
                    INSERT (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) VALUES(mergeArray(rw).C1, mergeArray(rw).C2,
                        mergeArray(rw).C3, mergeArray(rw).C4, mergeArray(rw).C5, mergeArray(rw).C6, 
                        mergeArray(rw).C7, mergeArray(rw).C8, mergeArray(rw).C9, mergeArray(rw).C10);
            -- DBMS_OUTPUT.PUT_LINE(mergeArray.count);
        EXCEPTION
            WHEN OTHERS THEN
                    DBMS_OUTPUT.PUT_LINE('error1');
        END;
    END LOOP;
    CLOSE cur;
    COMMIT;
END;
/
--耗時0.04秒
-- 驗證數據同步成功 
select count(*) from tab_test_Q;
--初始化tab_test_Q表數據,先從tab_test_C生成同步40000條數據,剩下10000條數據使用腳本同步過來
DROP TABLE tab_test_Q;
CREATE TABLE tab_test_Q AS SELECT * FROM tab_test_C where rownum < 40001;
create UNIQUE INDEX uid_test_q_1 on tab_test_Q(C10);
-- 驗證數據未同步成功 此時記錄數差1000
select count(*) from tab_test_Q;
-- 使用常規語法同步tab_test_C的數據到tab_test_Q
BEGIN
    for cur in (select * from tab_test_C)
    LOOP
        BEGIN
            INSERT INTO tab_test_Q(C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) 
            VALUES(cur.C1, cur.C2, cur.C3, cur.C4, cur.C5, cur.C6, cur.C7, cur.C8, cur.C9, cur.C10);
        EXCEPTION
            WHEN DUP_VAL_ON_INDEX THEN --唯一索引衝突時更新
                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
                WHERE C10 = cur.C10;
            WHEN OTHERS THEN
                    DBMS_OUTPUT.PUT_LINE('error1');
        END;
    END LOOP;
    COMMIT;
END;
/
--耗時14.77秒
-- 驗證數據同步成功
select count(*) from tab_test_Q;

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • keepalived keepalived: 基於vrrp(虛擬冗餘路由協議)的實現 virtual server: 對於IPVS vrrp_script: 調用外部腳本 nginx haproxy等輕量級的實現 所謂的vrrp就是為瞭解決前端路由器如果發生單點故障導致後方伺服器全部不能與外部通信的 ...
  • 一、Nginx簡介 概述:Nginx是一款由俄羅斯開發的開源的高性能HTTP伺服器和反向代理伺服器,同時支持IMAP/POP3/SMTP代理服務,其性能優勢著為顯著,官網上稱:單台nginx伺服器可以處理50000併發; 特點:高性能、穩定、消耗硬體資源小、能夠處理大併發,主要用於靜態的解析,動靜頁 ...
  • 本文轉載:https://www.cnblogs.com/jingmoxukong/p/6050172.html 概要 settings.xml有什麼用? 如果在Eclipse中使用過Maven插件,想必會有這個經驗:配置settings.xml文件的路徑。settings.xml文件是乾什麼的,為 ...
  • UCOSII 使用空閑任務的計數值(OSIdleCtr)來實現CPU使用率的統計,首先統計一個固定時間內的計數值保存下來為 (MAX),然後再開啟一個固定的時間段,當時間到達時得到另外一個(OSIdleCtr)的計數值保存為(ctr)。在這一段時間中,當運行用戶任務時空閑任務因為優先順序低無法執行那麼 ...
  • Insus.NET把它們寫成自定義函數,再程式中直接套用即可。 前一天: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- -- Author: Insus.NET -- Create date: 2019-05-15 -- Update dat ...
  • 以前寫過一個方法,先去參考《T-SQL判斷是否為今天》https://www.cnblogs.com/insus/archive/2012/03/22/2411209.html 今天使用一個更加簡單的方法來實現: 實例演示: ...
  • 以前寫過2篇,關於日期比較的,需求不同,每一篇均有參考價值。 《MS SQL日期比較函數》https://www.cnblogs.com/insus/archive/2011/06/24/2089005.html 《MS SQL兩個日期比較,獲取最大或最小的日期》https://www.cnblog ...
  • 函數一般是在數據上執行的,它給數據的轉換和處理提供了方便。只是將取出的數據進行處理,不會改變資料庫中的值。函數根據處理的數據分為單行函數和聚合函數(組函數),組函數又被稱作聚合函數,用於對多行數據進行操作,並返回一個單一的結果,組函數僅可用於選擇列表或查詢的having子句;單行函數對單個數值進行操 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...