大批量刪除 如何解決大批量資料儲存的效能問題

2021-10-14 16:21:29 字數 3389 閱讀 5754

一、背景在行業中所有基於實體的orm框架,均存在同乙個問題:在批量運算元據時,效能表現乏力。因為在批量儲存資料時,可能既包含新增的記錄,又包含更新或刪除的記錄,一般的orm框架必須為每一條記錄生成一條sql語句,然後一條一條的執行,這樣執行的效能非常差,而通常的優化方案是將資料分批儲存,但在資料量特別大時,儲存的效能表現依然無法接受。在erp的業務中,存在很多這種批量操作大量資料的場景,例如通過excel批量匯入大量資料,而且這類功能基本都出現在核心的業務模組,所以我們必須要攻克這個問題。

本文將介紹我們如何通過技術上不斷的優化,最終大幅提公升實體服務效能的過程。

二、初步優化如前所述,orm框架之所以在大批量資料儲存時效能差,主要原因是它必須一條一條的執行sql,熟悉資料庫技術的同學應該清楚,每次sql執行都會用到資料庫連線,而頻繁開啟連線會給資料庫造成巨大壓力。所以我們一開始想到的優化方案,就是將這批sql一次性發給資料庫執行,只開一次資料庫連線。

我們將sql一次性發給資料庫執行,確實大幅減少了開啟資料庫連線的次數,但依然存在效能問題。經過技術分析,我們發現原因在於發給資料庫執行的sql語句太大,造成了網路傳輸延遲過大。比如本次要批量儲存的資料行數有10萬,字段超過50個,需執行的sql語句就有10萬條,雖然是一次性執行,但sql本身可能有幾兆。

為了解決這個問題,我們需要將10萬條sql語句合併起來,變成幾條sql去執行。

三、第二輪優化我們實現合併sql語句方案時,遇到的第乙個問題是:批量儲存的資料,其中每一行的狀態是不一樣的,有些行可能是新增,有些行可能是更新,有些可能是刪除,不同型別的資料如何合併sql?

解決方案:將新增、更新、刪除三種型別的資料,分別合併成三條不同形式的sql語句進行執行。

我們緊接著遇到了第二個問題:要更新的每一行資料中,更新的字段也不一樣,可能第一行要更新a欄位,第二行要更新b欄位,每一行的update語句都不一樣,如何合併成一條sql?

解決方案:不管每一行要更新哪些字段,我們合併後的sql都更新所有字段,然後再使用乙個標識字段表示該欄位是否需要插入或更新,這樣就能用同一條sql更新所有行。

下面我們以批量儲存使用者表myuser為例,分別介紹在新增、更新、刪除場景下的sql如何合併。

myuser表的結構如下:

待儲存的記錄資料如下:

1、新增場景

核心思路:通過引數化和「insert...select」的sql語句,一次性將要新增的記錄插入myuser表(如果沒有值,則使用欄位的預設值代替)。

合併後的sql語句如下:

2、更新場景

核心思路:通過判斷字段值是否更新,動態拼接set語句的右值。

合併後的sql語句如下:

3、刪除場景

核心思路:通過in子查詢,根據id批量刪除記錄。

合併後的sql語句如下:

通過上述優化方法,sql語句本身大幅縮減,但依然存在兩個問題:

四、第三輪優化為了解決這兩個問題,我們通過sqlbulkcopy機制,快速的將待儲存資料一次性插入到資料庫的臨時表,sql語句通過關聯臨時表進行批量新增、修改、刪除,這樣sql語句本身可以變得更加簡短,而且因為去掉了引數化查詢,也規避了引數個數限制的問題。(microsoft sql server中提供了大容量複製程式實用工具 (bcp),用於快速將大型檔案批量複製到sql server資料庫中的表或檢視中。在ado.net中,sqlbulkcopy類提供了託管**的解決方案,支援類似的功能。)

我們的具體做法如下:

在資料庫中建立與子查詢同結構的臨時表,比如使用者表,可以建立對應的臨時表#temp_myuser;

使用sqlbulkcopy將所有待儲存的資料一次性插入到臨時表中;

合併後的sql通過關聯臨時表,將資料儲存到業務表中;

刪除臨時表,完成資料批量操作。

通過關聯臨時表合併成的最終sql語句如下:

1、新增場景:

2、更新場景:

3、刪除場景:

五、優化前後效能比對結果我們將優化前與優化後進行效能比對,在乙個50個字段的表中分別插入、修改資料,輸出使用的時間。

資料新增場景效能比對:

資料修改場景效能比對:

優化結果:新增或更新3萬行記錄,優化前需2分鐘左右,優化後僅需6秒左右,效能提公升近20倍。

六、總結我們從這次的效能優化中,得到了兩點收穫:

------ end ------

作者簡介

唐同學:架構師,目前負責erp執行平台整體架構設計和開發。

也許您還想看

erp快取實踐經驗分享

大資料列表頁面前端效能優化方案與實踐

.net最小工作執行緒對應用程式效能的影響

如何使用有序guid提公升資料庫讀寫效能

Linux rm刪除大批量檔案

在使用rm刪除大批量檔案時,有可能會遭遇 引數列太長 argument list too long 的問題。如下所示 bash bin rm argument list too long 檢視總共有多少個這類檔案,如下所示,總共有8348個檔案 oracle db server bdump ls l...

rsync大批量刪除檔案

1.一般情況 我們都是用rm 來刪除檔案操作 但是rm刪除檔案比較慢 2.這時候,我們可以使用rsync,通過一種巧妙的替換方式來實現目錄下大量檔案的刪除。3.如果想清空test目錄下的所有檔案,首先建立乙個空目錄 mkdir temp 然後執行 rsync a delete temp test 然...

linux 大批量刪除任務

一不小心投了巨多工,或者投遞的資源不合理時,想批量殺掉這些任務。kill的方法就不說了,我這裡用qdel的方法。用了這麼一條命令 qstat sed 1,2d awk f sed x n s n b x cat再用qdel刪除即可。這裡還是用了兩步,而且用sed將換行符替換為空格很複雜的樣子,不友好...