<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 262,  comments - 221,  trackbacks - 0
    一、測試環境:

    假設目前我們有一個表:test,該表的結構如下:
    SQL> desc test;
     Name                                      
    Null?    Type
     
    ----------------------------------------- -------- ----------------------------
     ID                                                   NUMBER
     SEQ                                                
    NUMBER

    現在我們向表中插入200W條數據,這200W條數據中有一半是重復的。
    create or replace procedure gen_duplicated_records as

      i 
    number;
      j 
    number;

    begin
      
    for i in 1 .. 2 loop
        
    for j in 1 .. 1000000 loop
          
    insert into test values (j, j + 10);
        
    end loop;
        
    commit;
      
    end loop;
    end;

    我們的最終目的就是剔除這一半的重復記錄。下面來看一下各種方法的使用及效率區別

    二、使用臨時表進行刪除:

    這個是最簡單的思路了,創建一張臨時表,將原表中的數據拷貝一半過去,再查詢出來。
    SQL> set timing on;
    SQL
    > 
    SQL
    > create table test_2 as select distinct * from test;

    Table created.

    Elapsed: 
    00:00:07.09
    SQL
    > 

    該方法耗時7.09秒,測試數據庫位于服務器上。考慮到服務器和本機位于同一個局域網內,該時間如果在真正的生產環境中應該至上延長1倍以上。

    三、使用rowid進行刪除:

    我們知道在Oracle中,rowid是用來唯一表示一條記錄的偽列,任意兩條記錄的rowid都是不同的,即便內容看起來一模一樣。所以我們的思路是:使用表的自連接,查找那些內容相同但rowid不同的記錄,即為重復記錄。然后隨意選擇其中一個rowid代表的記錄,刪除另一條記錄。

    我們來看一下其中id=1的記錄在自連接后的情況:
    SQL> select a.*, a.rowid, b.*, b.rowid from test a, test b where a.id = b.id and a.seq = b.seq and a
    .id 
    = 1;

            ID        SEQ ROWID                      ID        SEQ ROWID
    ---------- ---------- ------------------ ---------- ---------- ------------------
             1         11 AAAGHIAAJAAAAAKAAA          1         11 AAAGHIAAJAAAAAKAAA
             
    1         11 AAAGHIAAJAAAAgQAGX          1         11 AAAGHIAAJAAAAAKAAA
             
    1         11 AAAGHIAAJAAAAAKAAA          1         11 AAAGHIAAJAAAAgQAGX
             
    1         11 AAAGHIAAJAAAAgQAGX          1         11 AAAGHIAAJAAAAgQAGX

    Elapsed: 
    00:00:02.08
    SQL
    > 

    我們看到自連接后的4條記錄中有2條的rowid是不同的,說明這2條記錄就是重復記錄,所以我們可以通過選擇其中rowid較大或較小的記錄,來刪除剩余的記錄。但是這種方法的一個很大的缺點就是由于采用了“自連接”,對于像我這樣的測試表中有200W條記錄的情況,其自連接后的記錄數是一個天文數字(其實本人的測試就因為等待過久而不得不取消)。

    我們換另外一種方法:
    DELETE FROM test t1 
     
    WHERE t1.ROWID NOT IN (
         
    SELECT MAX(t2.rowid) 
           
    FROM test t2 
          
    WHERE t1.id = t2.id AND t1.seq = t2.seq);

    實踐證明,這種方法對大量數據的情況,效率依然是很低的。結果如同上一種方法。假如我們再結合group by呢?
    SQL> DELETE FROM test
      
    2   WHERE ROWID NOT IN (SELECT MAX(ROWID) FROM test GROUP BY id, seq);

    效果如同前面兩個方法一樣,大量的連接、排序、分組讓依靠rowid來刪除重復記錄變得很耗時,反而是采用方法1的情況下速度很快(本人測試了2次,都是連接測試服務器進行測試,第一次用時7.09秒,第二次用時14.656秒)。

    小結:
    在數據量不大的情況下,采用根據rowid或結合group by分組的方式是很快的,但是在海量數據的情況下則反而是方式一最快,因為省去了自連接、排序、分組的時間


    -------------------------------------------------------------
    生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
    posted on 2008-06-18 11:04 Paul Lin 閱讀(1649) 評論(0)  編輯  收藏 所屬分類: Oracle 開發
    <2008年6月>
    25262728293031
    1234567
    891011121314
    15161718192021
    22232425262728
    293012345

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    BlogJava熱點博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产午夜亚洲精品| 中文字幕免费在线看线人动作大片 | 午夜无遮挡羞羞漫画免费| 国产午夜亚洲精品不卡| 亚洲成色在线综合网站| 成年性羞羞视频免费观看无限| 久久久久亚洲国产AV麻豆| 久久青青成人亚洲精品| 国产精品另类激情久久久免费| 成人无码WWW免费视频| 亚洲无吗在线视频| 亚洲精品夜夜夜妓女网| 性生交片免费无码看人| 国内精品99亚洲免费高清| 亚洲av永久综合在线观看尤物| 亚洲精品高清一二区久久| 四虎1515hh永久久免费| 香蕉视频在线免费看| 亚洲色大成网站www永久网站| 国产成人毛片亚洲精品| 性感美女视频在线观看免费精品 | 暖暖免费日本在线中文| MM1313亚洲国产精品| 亚洲视频一区网站| 亚洲色欲久久久久综合网| 国产免费av片在线看| 久久精品中文字幕免费| 特级做a爰片毛片免费看| 在线aⅴ亚洲中文字幕| 亚洲第一中文字幕| 国产亚洲美女精品久久久2020 | 日韩视频免费在线| 国产妇乱子伦视频免费| 国内精品免费久久影院| 美女尿口扒开图片免费 | 久久国产高潮流白浆免费观看| 一区免费在线观看| 处破女第一次亚洲18分钟| 亚洲w码欧洲s码免费| 久久久亚洲裙底偷窥综合| 亚洲人JIZZ日本人|