大數據操作:刪除和去重
一些看似簡單的數據操作,當作用于海量數據集時,就會出現「意料之外,卻在情理之中」的問題,海量數據操作,需要採用特殊方法,才能「曲徑通幽」。在刪除海量數據時,需要注意日誌的增長,索引碎片的增加和資料庫的恢復模式,特別是利用大容量日誌操作,來減少日誌的增長和提高數據插入的速度。對於大數據去重,通過一些小小的改進,比如創建索引,設置忽略重複值選項等,能夠提高去重的效率。
一,從海量數據中刪除數據
從海量數據表中刪除一半數據,看似簡單,使用delete命令,如果真這麼干,SQL Server產生的事務日誌暴增,估計會把伺服器硬碟爆掉。資料庫的恢復模式會影響日誌文件的增長,在刪除海量數據時,根據採用的方法,相應地把恢復模式設置為simple,或bulk_logged 模式,能夠在很大程度上減少刪除操作產生的事務日誌,從而避免日誌暴增。
另外,在刪除數據時,把表上的多餘索引刪除(注意,是刪除多餘的索引),只保留一個必需的索引;在數據刪除完成之後,再重建索引,能夠提高數據刪除操作的性能。有人做過實驗,從存儲1.6億條記錄的大表中刪除數據,每刪除400萬條要消耗1.5 - 3小時,越到後面速度越慢,為什麼?這是因為,每次刪除數據時,資料庫都要相應地更新索引,這是很慢的硬碟 IO操作,並且,越到後面,索引碎片越多,更新索引就越慢,這就是在刪除400萬條記錄時,一開始只消耗1.5小時,後面要消耗3小時原因。
最後,根據保留數據佔總數據量的比例,選擇不同的方法刪除數據。如果大表中保留的數據較少,可以先把保留的數據存儲到臨時表中,然後,把原始表刪除,這樣能夠利用大容量日誌操作,來減少日誌的增長和提高數據插入的速度。
1,循環刪除,避免日誌文件暴增
在從海量數據表中刪除大量數據時,為了避免日誌文件暴增,通常採用循環刪除方法:首先設置恢復模式為simple,然後每次刪除操作都只刪除部分數據,這樣,當單個刪除操作執行完成時,事務日誌會被及時清理,事務日誌一般保持單個刪除操作的事務日誌量。
循環刪除的偽代碼如下,該方法仍有一些局限性,耗時過長,並且會長期使資料庫處於簡單恢復模式下:
--ALTER DATABASE database_name SET RECOVERY SIMPLE ;
while @index<@EndIndex begin delete table_name where index<=@index; set @index+=@Increment end
2,將數據插入導其他表中,把原表truncate
如果原始表有一半以上的數據要被刪除,從原始表中執行delete命令刪除數據,效率十分低下,可以考慮,把原始表中的數據通過select語句篩選出來,然後批量插入導新表中,這種方式利用了大容量日誌(Bulk Logged)操作的優勢。由於 SELECT INTO,INSERT SELECT 是大容量日誌操作,select命令不會產生大量日誌文件,因此,執行插入比執行刪除的效率更高。最後,執行drop命令,刪除整個原始表,幾乎不消耗任何時間。
--ALTER DATABASE database_name SET RECOVERY BULK_LOGGED ;
insert into new_table
select column_list
from original_table
drop table original_table
3,對分區表執行分區轉移操作
SQL Server的分區表實際上是一系列物理上獨立存儲的「表」(也叫做分區)構成的,如果要刪除的數據位於同一個分區,或者,一個分區中的數據都需要被刪除,那麼可以把該分區轉移(switch)到一個臨時表中,由於分區的轉移僅僅是元資料庫的變更,因此,不會產生任何的數據IO,分區轉移瞬間完成。被剝離的分區,通過drop命令刪除,整個過程僅僅會產生少量的IO操作,用於元數據變更;而不會產生用於數據刪除的IO操作,這種方法,耗時最短,資源消耗最小,效率最高。
alter table original_table
SWITCH PARTITION source_partition_number
TO temporary_table
drop table temporary_table
二,從海量數據中去重
數據去重,分為部分列去重和全部列去重,全部列去重,使用distinct子句來實現,由於distinct操作符會創建在tempdb中臨時表,因此,distinct操作是IO密集型的操作。而部分列去重,一般採用row_number排名函數來實現,也可以考慮使用忽略重複值的唯一索引來實現。在實際的項目開發中,部分列去重更為常見。
1,使用row_number函數來實現
選擇排名函數,是因為排名函數有部分列分區排序的功能:首先在部分列上創建索引,這樣資料庫引擎能夠根據索引列快速排序,然後通過row_number函數和cte來實現重複數據的刪除。在數據去重時,需要注意,如果刪除的數據量太大,資料庫引擎會產生大量的事務日誌,導致日誌文件暴增,在選擇該方法時,需要慎重。
create index index_name
on table_name
(
index_columns
)
with(data_compression=page);
with cte as
(
select index_columns,
row_number over(partition by index_columns order by ...) as rn
from table_name
)
delete
from cte
where rn>1
2,使用忽略重複值的唯一索引來實現
通過插入和忽略重複值實現部分列的去重,相對來說,更容易控制,用戶可以通過循環插入方式來執行,這樣,在單獨的一個事務中,控制插入數據的數量,能夠控制產生的事務日誌不至於太大,對於海量數據的去重,建議採用該方法。
創建一個臨時表,在部分列上創建忽略重複值的唯一索引:
create unique index index_name
on new_table
(
index_columns
)
with(ignore_dup_key=on)
由於SQL Server不允許在包含重複值的數據表上創建唯一索引,因此,必須創建一個新的空表,新表時原始表的結構的複製,在部分列上創建忽略重複值的唯一索引。在執行插入操作時, IGNORE_DUP_KEY 選項會忽略重複的索引鍵值,並拋出警告(Warning)。
※文件描述符與FILE
※cookie的路徑問題
※使用 keepalived 的ip漂移搭建主從web
※Vulkan Tutorial 18 重構交換鏈
TAG:科技優家 |
※大數據,大風險?數據監管任重道遠
※「殺熟」的大數據
※大數據被推崇的原因?
※大數據時代,如何藉助大數據進行直銷?
※大數據,豈止於大
※互聯網大項目中大數據的開放性和約束的剖析
※滴滴的大數據,殺熟了么
※大數據下的互聯網數據理論和數據備份與儲存
※大數據殺熟了嗎?
※大數據精準營銷,你被「殺熟」了嗎?
※機遇與挑戰:行政數據在大數據革命中的作用
※如何避免被商家的大數據「殺熟」?
※大數據中數據的研究和數據模塊的關聯需要有計劃和目標
※大數據挖掘師去純大數據公司還是去傳統行業單位的大數據分析部門?
※請看!大數據的作用僅僅在此
※「數據引導你的行為」:大數據背後的權力與不公
※互聯網項目中大數據的深度挖掘和數據變現的分析
※大數據架構與數據分析
※大數據的狂妄和南牆
※什麼是「大數據殺熟」?你被大數據宰過么