posts - 188,comments - 176,trackbacks - 0

          在大型的數(shù)據(jù)庫應(yīng)用中,我們經(jīng)常會有針對表與表之間的關(guān)鍵建進行字段更新,那么在這個時候,我們就不能寫簡單的update來實現(xiàn)更新操作,而要針對具體的數(shù)據(jù)量來進行批量的update,下面幾個例子是常用的SQL,將其做個對比,歡迎大家提出更好,更高效的SQL實現(xiàn)。


          數(shù)據(jù)庫:Oracle 9i  測試工具:PL/SQL

          定義2張測試表:T1,T2
          T1--大表 10000條 T1_FK_ID
          T2--小表 5000條  T2_PK_ID
          T1通過表中字段ID與T2的主鍵ID關(guān)聯(lián)


          模擬數(shù)據(jù)如下:

          --T2有5000條記錄
          create table T2 as select rownum id, a.* from all_objects a where 1=0;
          //T2表的字段和all_objects表字段類型以及默認值一致,但索引初始化了,需要重新設(shè)置

          --創(chuàng)建主鍵ID,向T2表copy數(shù)據(jù)
          alter table T2 add constraint T2_PK_ID primary key (ID);
          insert /*+ APPEND */ into T2 select rownum id, a.* from all_objects a where rownum<=5000;
           
          --T1有10000條記錄          
          create table T1 as select rownum sid, T2.* from T2 where 1=0;

          -- 創(chuàng)建外鍵ID,向T1表copy數(shù)據(jù)
          alter table T1 add constraint T1_FK_ID foreign key (ID) references t2 (ID);
          insert /*+ APPEND */ into T1 select rownum sid, T2.* from T2;
          insert /*+ APPEND */ into T1 select rownum sid, T2.* from T2;

          --更新Subobject_Name字段,初始為NULL
          update T2 set T2.Subobject_Name='StevenHuang'


          需求:我們希望能把T1表的Subobject_Name字段也全部更新成'StevenHuang',也就是說T1的10000條記錄都會得到更新,以下SQL語句均在PL/SQL命令窗口測試。

          方法一:
          寫PL/SQL,開cursor

          declare 
           l_varID 
          varchar2(20);
           l_varSubName 
          varchar2(30);
           
          cursor mycur is select T2.Id,T2.Subobject_Name from T2;
          begin 
           
          open mycur; 
           loop
                
          fetch mycur into l_varID,l_varSubName;
                
          exit when mycur %notfound;
                
          update T1 set T1.Subobject_Name = l_varSubName where T1.ID = l_varID;
           
          end loop;
           
          close mycur;
          end;

          ---耗時39.716s
          顯然這是最傳統(tǒng)的方法,如果數(shù)據(jù)量巨大的話(4000萬記),還會報”snapshot too old”錯誤退出,PL/SQL工具會掛掉

          方法二:
          用loop循環(huán),分批update

          declare 
            i 
          number;
            j 
          number;
          begin
            i :
          = 1;
            j :
          = 0;
          select count(*into j from T1;
            loop
              
          exit when i > j;
              
          update T1 set T1.Subobject_Name = (select T2.Subobject_Name from T2 where T1.ID = T2.ID) where T1.ID >= i and T1.ID < 

          (i 
          + 1000);
              i :
          = i + 1000;
            
          end loop;
          end;

          --耗時0.656s,這里一共循環(huán)了10次,如果數(shù)據(jù)量巨大的話,雖然能夠完成任務(wù),但是速度還是不能令人滿意。(例如我們將T1--大表增大到100000記錄 T2--小表增大到50000記錄,將耗時10.139s)

          方法三:
          --虛擬一張表來進行操作,在數(shù)據(jù)量大的情況下效率比方法二高很多.
             注:此語句下T1,T2表中必須有相應(yīng)的主外建關(guān)聯(lián),否則sql編譯不能通過.

          update (select T1.Subobject_Name A1,T2.Subobject_Name B1 from T1,T2 where T1.ID=T2.ID) set A1=B1; 

          --耗時3.234s (T1--大表增大到100000記錄 T2--小表增大到50000記錄)
          *以上所有操作都已經(jīng)將分析執(zhí)行計劃所需的時間排除在外

           
          轉(zhuǎn):http://alex.bloghome.cn/posts/144915.html  
          注:以上傳載的文章中的SQL經(jīng)過我測試,其結(jié)果和文章中的執(zhí)行結(jié)果的時間是吻合的,有興趣的朋友可以自己測試一下。

          posted on 2007-12-28 20:11 cheng 閱讀(11482) 評論(0)  編輯  收藏 所屬分類: Oracle
          主站蜘蛛池模板: 耿马| 永登县| 临澧县| 呼玛县| 昭通市| 错那县| 祥云县| 醴陵市| 繁峙县| 新安县| 海林市| 大姚县| 象山县| 临洮县| 楚雄市| 房山区| 泰安市| 崇信县| 兴宁市| 阿拉善盟| 孙吴县| 缙云县| 大港区| 高邑县| 延吉市| 海南省| 酒泉市| 富宁县| 自贡市| 县级市| 乌什县| 玉树县| 来宾市| 休宁县| 包头市| 库伦旗| 韩城市| 麻江县| 垦利县| 青铜峡市| 鹰潭市|