晚飯都沒吃,我一前端幫後端做了一點SQL優化,才避免了通宵

語言: CN / TW / HK

theme: vuepress highlight: tomorrow-night


攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第17天,點選檢視活動詳情

1、前言

其實感覺自己做的這點sql優化也算是比較常規的,沒什麼太大的難度。

最近上線了一個新系統,剛試點執行,使用者量不大還沒什麼大問題。但隨之培訓和大規模使用者開始使用後,問題出現了。而且出現了好多問題,大部分都是後端的,這裡就不細講了。說說與我前端相關的吧。由於我會一點後端。

  • 後端準備叫我開mysql客戶端,刪除多餘的資料

  • 刪就刪吧,但是要刪除的多餘資料還有點多

  • 刪除以後發現,還他媽有好多要刪除的資料,原來三個後端也同時在刪除資料
  • 於是我優化了三次sql語句,輕鬆實現批量刪除
  • 如果下次再有這種類似的情況,我得寫個相關的小工具了
  • 真的太浪費時間了,也不明白後端為啥不想想辦法呢?可能是因為線上bug的壓力,沒空想吧

2、看看重複記錄

根據這三個篩選條件,本來是可以確定唯一記錄的。可是並沒有,有的記錄甚至七八條重複的。

image.png

現在要做的就是把重複記錄都只保留一條。

3、開始刪除重複記錄

image.png

我這是在Navicat工具裡刪除的,如果只有一條或者幾條重複記錄這樣刪刪也就完了。但是後端大佬給了100個areaid。年份是固定的2022沒什麼好說的,每個areaid下的name有89個不重複的。如果一個name一個name的刪除要到猴年馬月了。這裡如上圖所示就刪除其中一條就好了。

image.png

這裡是後端給我的要刪除的areaid,也就是具體的name是不太清楚的,因為太多了,還得自己去查。

4、優化刪除

因為這是三個查詢條件下的資料,如果不加name,把所有這個areaid下的,所有的name 資料可能就有很多了,每次要根據給的areaid進行查詢(年份是固定的這裡我就不說了)

select s.name as 'sname', s.* from CollectDataSummary s where s.areaid = 23 and s.nf = 2022 order by s.name desc

image.png

可以看到我只是加了一個排序,然後最上面幾條就可以看出三條記錄是重複的就要進行刪除其中的兩條。其實這裡正式環境使用者量很多,產生一樣的資料也非常多,所以刪除起來還是比較麻煩的。

這裡我想了一下,先查出一個areaid下有重複記錄的name select s.name from CollectDataSummary s where s.areaid = 23 and s.nf = 2022 group by s.`name` HAVING count(s.`name`)> 1

image.png

然後再查詢一次,將上面查詢的重複的name也作為條件進行查詢 select * from CollectDataSummary c where c.areaid = 23 and c.nf = 2022 and c.name in (select s.name from CollectDataSummary s where s.areaid = 23 and s.nf = 2022 group by s.`name` HAVING count(s.`name`)> 1)

image.png

這樣查出來可以發現,可以點點將重複的記錄都進行刪除。勉強一下幹了半個小時,我把後端給我的areaid都刪除了。

並且我把我這個sql給他們,他們三個後端也在進行刪除了,一頓操作後,我手裡的這一批幾十個刪完了。

然後我問了一下都刪完了嗎,尼瑪還有好多好多,按照現在這樣刪除,他們三個人可能還要刪除三個小時,於是我又陷入了沉思.....

5、再次優化刪除

想了想,我可以根據name進行分組,然後其實就是隻選擇了相同資料的其中一行

select a.id from CollectDataSummary a where a.areaid in ( 23) and a.nf=2022 group by a.name having count(a.name)>1

這樣的話,我就把這些資料留下吧,然後結合了一下4、優化刪除中的sql

image.png

把通過group by 單獨查詢出來的一組資料通過not in 過濾掉,這樣就留下這組資料,其他所有的資料都是要刪除的,這樣的話就是查詢出來的資料,Ctrl + A全選再加上 Delete就完事了,還是非常的方便

6、總結

  • 雖然我覺得這次我幫了大忙,但是這點sql好像也沒啥技術含量

  • 其實我想到還可以直接寫個delete語句的,但是這樣只能看到刪除的資料量

  • 然後再不行寫一個儲存過程將要刪除的areaid傳進去,迴圈慢慢刪除
  • 還有大招我直接寫個頁面呼叫介面來刪除,可能更靈活一些,當然要做好檢查和確認

第二天想去再看看的時候,資料庫已經訪問不了了,行吧,繼續搞我的前端吧,有空去試試mysql的儲存過程,免的啥時候真能派上用場。