如何优雅的实现DML批量操作
如何優雅的實現DML批量操作(轉載)
?
昨天處理了一個業務同學的數據需求,簡單來說就是對一張大表做一下數據清理,數據量在8千萬左右,需要保留近一個月的數據,大概是400萬左右。
對于數據的刪除處理,尤其是大表的處理,可以借助MySQL特有的一種處理策略,可以參考之前的文章:
從處理方式來看,基本就是做了rename,把原來表的數據轉置到一個中間庫里面,然后補錄數據,對于日志型的數據表來說是很有必要的。
?
但是這種方式涉及幾個細節,主要的出發點就是怎么樣讓這個操作更加可控,我所說的意思是整個處理過程你可以按部就班的操作,該備份備份,而補錄補錄,而對線上的切換過程都是毫秒級完成,幾乎產生不了直接影響,要實現這個看似不大可能的需求,我們就需要設定幾個邊界:
1)數據類型為流水型業務,不涉及事務處理
2)數據流程不會修改歷史數據,僅僅參考近N(可以為N,也可以為當天)的數據
3)操作的時機不是業務高峰期
4)能夠接受秒級的數據寫入閃斷
明確了這些不能夠之后,我們來看看怎么來實現這個目標,可以參考如下的流程圖:
?
所以要實現這個目標,我們需要盡可能保證中轉表的數據要盡可能完整,而且要保證數據切換能夠高效完成。
那么我們處理的思路就是增量迭代,即最后的切換階段耗時最短,我們可以提前復制需要補錄的數據,同時對當天的數據進行增量的補錄,然后開始切換。
我們可以參考如下的步驟:
1)首先創建同樣結構的表,包括索引,一個表是做備份,一個是作為中轉。
mysql> create table cmec_log_arch.log like cmec_log.log;
mysql>?create table cmec_log_arch.log_new?like cmec_log.log;
2)需要把近一個月的數據表現存放到中轉表log_new里面,為了提高效率,我們先保證當天的數據有效。
mysql> ?insert into cmec_log_arch.log_new? select * from cmec_log.log? where cdate between '2019-09-18' and '2019-09-18 10:00:00';? ?--當前時間大于10:00:00,但是間隔不大
我們可以縮小時間間隔,完成增量數據的補錄,直到增量數據的補錄時長控制在秒級(數據集越小,處理時長越短)
2)然后切換表
mysql> RENAME TABLE cmec_log.log? ? TO cmec_log_arch.log_bak,
? ? ? ? ? ? ? ? ? cmec_log_arch.log? ? TO cmec_log.log,
? ? ? ? ? ? ? ? ? cmec_log_arch.log_bak TO cmec_log_arch.log;?
Query OK, 0 rows affected (0.18 sec)
整個切換過程是很快的。
4)接著我們進行歷史數據的補錄,完成了當天數據的補錄,我們只需要關注歷史數據的范圍即可。
為了盡可能降低對岸上環境的應縣個,我們需要縮小補錄的時間范圍,比如按照如下的方式來進行補錄:insert into cmec_log.log select * from cmec_log_arch.log_new where cdate between '2019-09-16'? and '2019-09-17';? ?
因為結果集相對小一些,處理過程對已有的數據處理線程的效率影響最小,可以避免大結果集導致服務阻塞的情況。
當然關鍵的部分是整個流程梳理完善后固定下來,我們可以把它轉換成一個腳本,這樣后續的操作我們只需要輸入表名,保留的時間范圍即可完成這個看起來略微復雜的需求了。?
原文鏈接:https://blog.csdn.net/yangjianrong1985/article/details/102479380
?
總結
以上是生活随笔為你收集整理的如何优雅的实现DML批量操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何优化MySQL千万级大表
- 下一篇: SELECT COUNT语句