因為業務需要對一張大表的乙個列值進行update更新,表中有資料一億多條,為了更新這一億多條資料,我做了一下嘗試,給各位同學留個前車之鑑。
表名:test
列名:name varchar2(50)
方法一:
直接對大表update,
語句:update test set name=replace(name,chr(13),'');
結果:執行12個小時候,sql仍未執行完成,於是在執行12個小時之後,我把這個交易kill 了;
後果:最終耗費了48小時來完成資料回滾,給資料庫帶來了嚴重的的壓力,同時造成了大量的鎖等待,結局很悲慘。
方法二:
吸收了方法一的教訓,一次修改的話,undo資料太大,對資料庫效能有嚴重的影響,書寫了乙個儲存過程,每一萬條資料提交一次,同時新建一張表t1和sequence sq_test,記錄已經修改的條數,sql如下:
create or replace procedure updatebigtablerecord as
cursor c_cursor is
select rowid from test;
v_rowid varchar(30);
x number := 0;
y number(30);
begin
open c_cursor;
loop
fetch c_cursor
into v_rowid;
exit when c_cursor %notfound;
update test
set name = replace(name, chr(13), '')
where rowid = v_rowid;
insert into t1(id) values (sq_test.nextval);
x := x + 1;
if x > 10000 then
commit;
x := 0;
end if;
end loop;
close c_cursor;
exception
when others then
rollback;
commit;
end;
經過測過,此方法明顯優於第一種方法,可以及時的釋放鎖資源,同時可以檢視資料修改進度,經過測試,update速度約為每小時100萬,這個速度 用來修改一億條資料的話,估計需要100個小時,大概是4天4夜的時間。
結果:方法不適用,取消了
後果:又給資料庫增加了undo壓力
附帶影響:磁碟陣列的io等待嚴重,以至於後來在增加表空間時,速度緩慢,新增5m的表空間,耗時五分鐘,大家可以想象一下大量的undo帶來的後果,建議大家以後盡量回滾事物,尤其是對待一些大的事務。
方法三:
以上兩種方法都是通過sql 使用update 來更新表中的資料,這種更新在帶來大量的undo的同時也帶來大量的redo,且速度緩慢。
最終通過下面的方法解決問題,create table as select..
sql如下:
create table bk_test
id,name,
) parallel (degree 2)
asselect
id,replace(name, chr(13), '') name ,
from test nologging;
整個過程耗時00:03:59.66
方法四:
如果你覺得第三種方法建立新錶將會耗費一些磁碟io和磁碟空間,不願意這麼做,還有第四種方法:
在表之上建立檢視。
sql:
create or replace view v1_test(name) as select replace(name, chr(13), '') name from test;
alter table test add primary key(name);
mysql 大表優化 持續更新
單錶優化 除非單錶資料未來會一直不斷 否則不要一開始就考慮拆分,拆分會帶來邏輯 部署 運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題的。而事實上很多時候mysql單錶的效能依然有不少優化空間,甚至能正常支撐千萬級以上的資料量 字段 索引 查詢sql 總結 ...
mysql 大表 驅動 MySQL小表驅動大表
在了解之前要先了解對應語法 in 與 exist。in後的括號的表示式結果要求先輸出一列字段。與之前的搜尋字段匹配,匹配到相同則返回對應行。mysql的執行順序是先執行子查詢,然後執行主查詢,用子查詢的結果按條匹配主查詢。exist後的括號裡則無輸出要求,exist判斷後面的結果集中有沒有行,有行則...
mysql大表修改表名原理 mysql大表修改結構
alter table執行時會對原表進行臨時複製,在副本上進行更改,然後刪除原表,再對新錶進行重新命名。在執行alter table時,其它使用者可以閱讀原表,但是對錶的更新和修改的操作將被延遲,直到新錶生成為止。新錶生成後,這些更新和修改資訊會自動轉移到新表上。注意,如果您在執行alter tab...