重慶分公司,新征程啟航
為企業提供網站建設、域名注冊、服務器等服務
為企業提供網站建設、域名注冊、服務器等服務
ORACLE中如果表數據量很大(M級或更大),update某個字段是很慢的(如我的HIS項目中更新歷史業務流程表,160萬條記錄,用CURSOR來更新,1000條COMMIT一次,花了4天也沒更新完),后來嘗試過的改進辦法有:
創新互聯建站于2013年開始,是專業互聯網技術服務公司,擁有項目網站設計、成都網站設計網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元澄城做網站,已為上家服務,為澄城各地企業和個人服務,聯系電話:13518219792
1.把表上的LOGGING取消
2.把表上的INDEX取消
但是依然很慢,無奈下找到這個:
在這個主題問答里,ORA官方提了一種處理的辦法:
1.利用CREATE table as select xxxxx的辦法來生成一新表T1
2.在T1上創建與目標表一樣的索引
3.把目標表刪除或RENAME(注意備份以備反悔)
4.把T1改名成目標表
試了一下,果然非常地快,我的任務差不多在2Min就完成了。
如csywdk.table_room是一張大表,要刪除其中bakfwid在noNewYWFW20081205中的記錄,且要更新bakfwid在imp_table_room中記錄的ROOM_LOC為imp_table_room.room_loc:
(1)創建新表
create table tmp_new_table_room081205 as
select t1.ROOM_ID,t1.NEWROOMID,t1.BUILDID,t1.TFH,t1.DKH,t1.BUILD_NO,t1.LAYER_NO,t1.ROOM_NO,t1.ROOM_NAME,
decode(t2.bakfwid,null,t1.ROOM_LOC,t2.room_loc)
t1.ROOM_AREA,
t1.SURTYPE,t1.LAYER_NAME,t1.DEVDEP,t1.CELL,t1.DELFLAG,t1.QXXZ,t1.SJSJLSH,t1.FD,t1.ID,t1.BAKFWID
from csywdk.table_room t1 left join imp_table_room t2 on t1.bakfwid=t2.bakfwid
where not exists(select 1 from noNewYWFW20081205 t3 where t3.bakfwid=t1.bakfwid)
(2)創建備份表
create table Table_room081205 as
select * from csywdk.table_room
(3)替換原表
drop table sde.table_room
create table sde.table_room as
select * from tmp_new_table_room081205
在這個問答里還提到一句ORA PL/SQL效率相關的話:
“能用一句語句處理的任務決不要用多句編程來實現”。
原來老是怕一句執行時,回滾段不夠大,看來只能準備好硬盤為上策了
你可以寫一個存儲過程來執行,由于數據量大,如果直接更新,數據庫UNDO表空間肯定會滿,會產生異常。
過程如下,給你參考下。
CREATE OR REPLACE PROCEDURE UPDATE_TABLES
AS
TYPE T_MW IS TABLE OF ROWID;
T_T_MW T_MW;
CURSOR V_CUR IS
SELECT ROWID FROM T ;
BEGIN
OPEN V_CUR;
LOOP
FETCH V_CUR BULK COLLECT
INTO T_T_MW LIMIT 80000;
FOR C1 IN 1 .. T_T_MW.COUNT LOOP
UPDATE T NOLOGGING
SET 要改的列
WHERE ROWID=T_T_MW(C1);
END LOOP;
COMMIT;
EXIT WHEN V_CUR%NOTFOUND;
END LOOP;
CLOSE V_CUR;
COMMIT;
END;
該過程可一次提交80000行。你也可以根據需求改。
操作步驟如下:
準備數據:在excel中構造出需要的數據
2.將excel中的數據另存為文本文件(有制表符分隔的)
3.將新保存到文本文件中的數據導入到pl*sql中
在pl*sql中選擇tools--text
importer,在出現的窗口中選擇"Data
from
Textfile",然后再選擇"Open
data
file",
在彈出的文件選擇框中選中保存有數據的文本文件,此時將會看到data
from
textfile中顯示將要導入的數據
4.在configuration中進行如下配置
注:如果不將"Name
in
header"勾選上會導致字段名也當做記錄被導入到數據庫中,從而導致數據錯誤
5.點擊data
to
oracle,選擇將要導入數據的表,并在fields中將文本中的字段與表中的字段進行關聯
6.點擊import按鈕進行導入
7.查看導入的數據
OK,至此數據導入成功。
建議你通過某個條件把這150萬條記錄,分成多個部分,寫個存儲過程,依次執行,執行完一部分就提交一部分。
這樣即即減少了對內存的要求,也防止玩意update出錯,還要花費大量的時間在回滾上。
UPDATE C_TABLE C SET C.NAME1= C.NAME2 WHERE C.NAME2 IS NOT NULL AND ROWNUM = 3000;
你的條件,C.NAME2 IS NOT NULL ,所能查詢出的數據始終沒變,再加上ROWNUM = 3000,也是結果始終未變,要么第二次查詢3000-6000,或者查詢的字段NAME2發生變化,使得數據查詢結果變化。
可以用游標來執行更新,也可以用update語句更新。
但是oracle沒有update from語句,可以用子查詢來給源數據表的字段賦值,如果需要賦多個值的話,則用括號括起來,格式:
update?table_name
set?(field1,?field2,?...?)?=?(select?value1,?value2,?...?from?source_table)
where?...
而where條件中則可以用exists測試是否要更新記錄。更新語句大概這樣:
update?A?s1
set?a5?=?(select?b6?
from?B?s2?
where?s2.b1?=?s1.a1?and?s2.b2?=?s1.a2?and?s2.b3?=?s1.a3?and?rownum?=?1)
where?exists?(
select?b6?
from?B?s2?
where?s2.b1?=?s1.a1?and?s2.b2?=?s1.a2?and?s2.b3?=?s1.a3?and?rownum?=?1
)
即賦值子句和where條件是類似的。