夢幻之旅

          DEBUG - 天道酬勤

             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            671 隨筆 :: 6 文章 :: 256 評論 :: 0 Trackbacks

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


          數據庫:Oracle 9i  測試工具:PL/SQL

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


          模擬數據如下:

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

          --創建主鍵ID,向T2表copy數據
          alter table T2 add constraint T2_PK_ID primary key (ID);
          insert 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;

          -- 創建外鍵ID,向T1表copy數據
          alter table T1 add constraint T1_FK_ID foreign key (ID) references t2 (ID);
          insert into T1 select rownum sid, T2.* from T2;
          insert 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
          顯然這是最傳統的方法,如果數據量巨大的話(4000萬記),還會報”snapshot too old”錯誤退出,PL/SQL工具會掛掉

          方法二:
          用loop循環,分批update

          declare 
            
          number
          ;
            
          number
          ;
          begin

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

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

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

          方法三:
          --虛擬一張表來進行操作,在數據量大的情況下效率比方法二高很多.
             注:此語句下T1,T2表中必須有相應的主外建關聯,否則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記錄)
          *以上所有操作都已經將分析執行計劃所需的時間排除在外

          posted on 2013-01-07 13:14 HUIKK 閱讀(574) 評論(0)  編輯  收藏 所屬分類: DataBase
          主站蜘蛛池模板: 张北县| 高邮市| 临汾市| 云南省| 仁怀市| 沭阳县| 山阳县| 和林格尔县| 文山县| 景宁| 和田市| 宁国市| 永昌县| 宜州市| 两当县| 洛扎县| 田东县| 北流市| 靖安县| 盖州市| 灵台县| 弥勒县| 松阳县| 通州区| 石棉县| 吉林市| 潼关县| 嘉兴市| 景东| 兖州市| 缙云县| 织金县| 云林县| 揭东县| 香港 | 泰州市| 兴和县| 镇远县| 昌吉市| 永清县| 巴林右旗|