從MS SQL刪除大資料說開去

2022-02-23 09:26:51 字數 4334 閱讀 9573

對於資料庫中刪除資料,你說要注意什麼呢?**怎樣寫?

多數同學看到這兩個問題,想都不想就說,就乙個delete語句,注意刪除的條件不要刪除錯了就是,有什麼好注意的!

是的,可以我再問一下,刪除動作是會寫日誌的,你放日誌的磁碟夠空間嗎?

1. 我先舉個實際的工作問題;

2. 整理t-sql的刪除資料的語句和寫法;

3. 解決這個工作中的問題和效果總結。

先舉個我實際工作中的事例,我們在這樣的乙個應用,每天定時收集一些資料寫入資料庫中,資料庫中有一批表(十幾個)存放這些資料,由於資料量很大,三個月的單錶資料在1億以上,所以,我們只用表儲存90天的資料,用於做什麼我們在這裡不關心好不好。在每天都有乙個job去刪除90天以前的資料。由於這是很早前,我的前輩所做的,現在人已不在這公司了。這些表所有的動作就以下的語句來刪除:

1:  

delete

from dbo.s5_bintest_detail

2:  

where bintestid in (select bintestid

3:  

from dbo.s5_bintest_info

4:  

where ts 5: )

6:  

and datediff(dd,(select

min(ts) from s5_bintest_info),ts)<=0

7:
8:  

delete

from dbo.s5_bintest_info where ts 9:

and datediff(dd,(select

min(ts) from s5_bintest_info),ts)<=0

這只是一次只刪除一天的資料,也就是日期最早的,90天以前的。昨晚就收到了以下的伺服器報警:

我看到平時伺服器上各磁碟的空間使用情況如下,d盤是日誌檔案所在的盤,平時大概有95g的可用空間;

e盤是資料檔案存放的盤,平時有170g的可用空間。由於資料每天的新增和刪除的量都基本平衡,所以也就沒有多大的變化。

現在看到資料庫檔案已有121g這麼大。多個億級別的表了。

平時的日誌檔案幾百m。

這報警是d盤小於40g,那就是說日誌檔案增長了45g以上,那時也正好是刪除資料的job在執行。在我檢查這些刪除動作的語句時,發現了問題,就是沒有考慮刪除大資料時日誌增長與磁碟空間的關係。這樣下去,可能那一次就掛了。

再說說刪除資料的方式:

對於刪除資料,t-sql提供了兩個從表中刪除資料行的語句:delete和truncate.

delete 語句是標準的sql語句,它用於根據指定的謂詞(條件)從表中刪除資料。這個標準的語句只有兩個子句:用於指定目標表名的from子句和用於指定謂調整條件的where子句。只有能讓謂詞條件計算結果為true的行才會被刪除。

例如:

delete

from dbo.s5_bintest_info where ts 這是刪除表s5_bintest_info中時間欄位ts早於90天的資料。

delete語句採用的是完整模式的日誌處理,當刪除大量資料時,可能會花費大量的時間還有需要大量的日誌存放空間。

truncate語句不是標準的sql語句,它用於刪除表中所有的行。與delete語句不同,truncate不需要加條件,如:

truncate table dbo.s5_bintest_info;

和delete語句相比,truncate具有以最小模式記錄日誌和優點。和delete語句的完整模式在效能上有巨大的差異。truncate的速度最快。當表中有標識列時,delete不會改變標識列的值,truncate則會重置為最初的種子值。

再說說基於聯接的delete,t-sql支援一種基於聯接的delete語法,這不是一種標準的sql語法。聯接本身就有過慮的作用,因為它有乙個基於謂詞的過濾器(on子句)。通過聯接可以訪問另乙個表中相關行的屬性(列),並在where子句中引用這些屬性,這就意味著可以根據對另乙個表中相關行的屬性定義的過慮器來刪除表中的資料行。例如:

delete from s5

from dbo.s5_bintest_info as s5

join dbo.s5_bintest_info_dtl as dtl

on s5.id=dtl.id

where dtl.qty=1;

這和select語句非常相似,delete語句在邏輯上第乙個處理的子句是from子句(第二行from dbo.s5_bintest_info as s5的這個),接著處理where子句,最後才是delete子句。

這也可以用查詢子句來實現同樣的處理:

delete from dbo.s5_bintest_info

where exists(select 1 from dbo.s5_bintest_info_dtl as dtl

where s5_bintest_info .id=dtl.id and dtl.qty=1);

這裡的查詢子句的方式是標準的sql語句,我更喜歡使用標準sql。

再回到我這個工作中的問題,我想用分批刪除的方式來處理。一次刪除合理資料的記錄,多刪除幾次就可以了。

由於我為裡是有id的,所以一次刪除乙個id號的記錄,以下是更改後的迴圈方式實現原始碼。

1:  --2012-03-30,因刪除大資料問題,以下更改為分批刪除的方式實現
2:  

declare @minid int;

3:  

declare @n int;

4:      --取出要刪除的90天前的記錄的id
5:  

select bintestid into #s5id

6:  

from dbo.s5_bintest_info

7:  

where ts 8: --以要刪除的id數量為迴圈變數,因為id號可能不連續

9:  

select @n=(select

count(1) from #s5id);

10:  

while (@n>0)

11:  

begin

12:  

-- 一次刪除乙個id對應的資料

13:  

select @minid=min(bintestid) from #s5id;

14:  

delete

from dbo.s5_bintest_detail

15:  

where bintestid=@minid;

16:  

delete

from dbo.s5_bintest_info

17:  

where bintestid=@minid;

18:         --從臨時表中去除已刪除的id號
19:  

delete #s5id where bintestid=@minid;

20:         --更改剩餘要刪除的id數,這是迴圈變數
21:  

select @n=(select

count(1) from #s5id);

22:  

end

23:  

drop

table #s5id;

如果對於沒有id的資料表,我們可以用top的方式來刪除。

我使用這樣的方式執行時,日誌基本沒有增長,因為刪除一次很少的資料,成功後會釋放,再使用。

您,刪除資料時考慮語法和條件還有大量資料的日誌增長空間問題了嗎?

大資料時代 從謝頓計畫說開去

學科前沿講座 課程報告,刪去抄襲和湊字數部分的支離破碎版本 狄更斯在 雙城記 第一段裡這樣寫 這是最好的時代,這是最壞的時代 這是智慧型的時代,這是愚蠢的時代 這是信仰的時期,這是懷疑的時期 這是光明的季節,這是黑暗的季節 這是希望之春,這是失望之冬 人們面前有著各樣事物,人們面前一無所有 人們正在...

MS SQL入門基礎 刪除資料

11.2.1 delete 語法 delete 語句用來從表中刪除資料,其語法為 各引數說明如下 from 此引數為可選選項,用於連線delete 關鍵字和要刪除資料的物件名稱。table name 指定要刪除資料的表。with n 指定乙個或多個目標表允許的表提示。view name 指定用於刪除...

MYSQL大資料刪除

由於公司需要刪除一年前的資料。所以參考了部分資料,整理了刪除部分大資料的較合理方法。1選擇不需要刪除的資料,並把它們存在一張相同結構的空表裡 insert into t copy select from t where 把要刪除大量資料的表中不需要刪除的資料轉存到另外一張表中2重新命名原始表,並給新...