mysql批量更新數據(性能優化)


    最近做的游戲,上線后出了不少問題,所以我就經常去查數據庫數據,翻各種日志等,但是在查詢的時候發現好蛋疼,有些地方的時間是寫 "2016-08-11 20:13:02"這種格式,有些地方的時間是寫 "1470917582000"這種格式,然后多張表數據進行對比的時候就很蛋疼,我得不停進行時間轉換,惡心得不行。最后實在忍不了,我要統一時間格式(由於時間都是單獨一個字段記錄,所以比較好處理),兩種格式,很明顯,對於查數據來說,第一種格式更直觀,所以就決定了,將數據庫日志類、郵件類的表的時間,統一成"2016-08-11 20:13:02"這種格式。

   想了一下,沒法單純用mysql語句直轉換,於是就自己寫了一個腳本來轉換時間格式(新增的很好處理,主要問題是要將之前記錄的數據轉換一次,在服務器維護的時候,進行處理)。

   一開始想法很簡單(很少用mysql,使用的時候也都是簡單使用而已),就是把數據庫數據全部select出來,然后一條條update,本地測試,沒啥問題。后面就把外網的玩家部分數據導入進來,進行測試。不導不知道,一導嚇一跳,內存爆了,哈哈,外網數據量太大,根本就沒法讓我一下子全select出來。那咋辦呢,想了一下,其實我並不需要那么多數據,對每條記錄,我只要select出key和time就行了,說干就干,試了一下,好像不會爆了,但是發現他的執行速度超級慢,一百萬條記錄,跑了五六個小時,這還只是部分數據啊,要是是全部數據,那得跑多久啊,停服維護這么久,還不被罵死。沒辦法,那就優化吧。

    首先想到的是,一條一條更新的速度太慢了,然后就想批量更新,一次更新N條數據。實踐是檢驗真理的唯一標准,不一會兒,代碼就敲完了,重新試了一下,效果依舊不理想。啊哦,真是要崩潰!后面又想到了利用異步,我一下子開多個mysql連接,同時處理,可是依舊慢的一筆。然后就放棄了,更新的效率肯定是滿足不了了。然后就想着繞彎子了,我新建一張表,把舊表數據取出來,處理完后,直接插入到新表,然后再把舊表刪除,把新表重新命名成舊表的名字。想想,insert into的速度應該會比update快不少。但是要把舊表數據全部取出來,內存會爆掉,所以我就用慢慢取的方式, select+limit。試了一下,速度快了不少,但是感覺也得跑個一個多小時。雖然快了很多,但是這速度肯定還是不行。

   然后試了下,select的時候用select + where + order by + limit的方法,where和order by都是用time去處理,跑了一下,十來分鍾就搞定了。后面想想,where和order by的時候用表的主鍵去處理,應該會快點,然后就試了一下,哇塞,效果很明顯,select + where + order by + limit的方法(用主鍵去處理where 和order by) ,一分鍾就處理完了所有數據。取一次數據,處理完數據后,插入一次數據,可以根據自己的數據量大小,適當調整一次要select多少條數據出來。記住,select出來后,處理完,一次性插入新表,不要一條條插入!

   最終結果,用select + where + order by + limit的方法(用主鍵去處理where 和order by) ,一分鍾左右就處理完了五百萬條左右的數據,有好幾張表,其中有兩張表都各有一兩百萬條的數據,而最初的那種逐條update的方法,預計得十個小時以上。雖然幾經波折,最后終於放心地交差了。

   重點:普通的select方式取出來速度很慢,插入新表的方案,性能的關鍵點在於從舊表select出數據,至於插入,只要使用批量插入就好啦!

   小插曲: 創建新表的時候,我是用復制舊表結構的方式去創建的,復制舊表結構的時候,記得使用create table newTableName like oldTableName的方式,不然會沒有把舊表的索引復制過來


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM