MYSQL開發性能研究——INSERT,REPLACE,INSERT-UPDATE性能比較

1、爲何要有這個實驗html

咱們的系統是批處理系統,相似於管道的架構。而各個數據表就是管道的兩端,而咱們的程序就相似於管道自己。咱們所須要作的事情無非就是從A表抽取數據,通過必定過濾、彙總等操做放置到B表。若是出現了錯誤,那麼就從從新跑這一個管道。因此說,咱們的系統其實根本就不要什麼事務性,無非就是掛了把表給TRUNCATE(或者有條件地DELETE)一下,而後重跑就好了。mysql

這樣一來,對於select語句就相對比較容易,基本上不須要作JOIN操做。然而對於寫操做就有一些要求。好比說,須要處理主鍵重複(可能以前跑掛了,如今須要重跑,究竟是提示錯誤呢,仍是作個REPLACE或者UPDATE)等等問題。sql

在引入了MYSQL以後,咱們發現MYSQL在SQL語句層面就提供了對於相似問題的解決。包括了INSERT,REPLACE,INSERT-ON-DUPLICATE的操做。具體的說明請查看這裏。惟一須要注意的是INSERT-ON-DUPLICATE這個操做,在UPDATE裏面的VALUES的含義是INSERT列表裏的那個固定值,若是須要引用數據表中原來的值,仍是直接使用列名便可,無需用VALUES包裝一下。數據庫

 

 

2、實驗準備多線程

我仍然是採用了在咱們這裏可能用到的最大的表,該表有近200個字段。實驗環境也和上一篇文章中的同樣。有了那篇文章中的比較,我就直接使用了10條多行插入的方法,也是每5000條提交一次。爲了作個比較,我特地製做了一個傳統的INSERT-UPDATE操做。該操做先進行INSERT插入動做,而後檢查輸出,若是是出現了「主鍵重複」的錯誤,那麼直接調用UPDATE語句,用相同的數據替換那行(就是直接原值覆蓋)。注意,這種辦法是沒有辦法作到多行插入的。架構

一樣,爲了讓場景更加真實。我在同一個MYSQL服務上建立了三個數據庫,其中都建立了該表。並且全部的操做都直接針對該三張表進行。我在代碼裏使用的工具是我本身寫的一個類庫。經過多線程鏈接到多庫(一庫一鏈接)而後主線程向全部線程發送一句INSERT/REPLACE/INSERT-UPDATE/INSERT-ON-DUPLICATE-KEY命令,等待全部線程都返回繼續向下。全部的COMMIT操做都是線程主動根據AFFECTED ROWS的累積量本身選擇作。工具

再強調一下,機器很爛,TPS沒有意義。只是看個趨勢。
性能

 

3、實驗結果.net

說明:線程

  • 多行INSERT空表——使用」INSERT INTO … VALUES (..), (..), (..), … 「的方式往一張空表裏面插入數據。
  • INSERT-UPDATE——在上一步驟的基礎上,該操做先進行INSERT插入動做(一條一條INSERT),而後檢查錯誤輸出,若是是出現了「主鍵重複」的錯誤,那麼直接調用UPDATE語句,用相同的數據替換那行(就是直接原值覆蓋)。
  • 多行REPLACE空表——使用「REPLACE INSERT INTO … VALUES (..), (..), (..), … 」的方式往一張空表裏面插入數據。
  • INSERT-DUPLICATE——使用 INSERT INTO .. VALUES (..), (..), (..), … ON DUPLICATE KEY UPDATE …」的語法在上一步驟的基礎上進行操做。

image

 

結論以下:

  • 對於空表操做,REPLACE的性能和INSERT的差很少,可是他還有一個額外的好處,就是能夠進行覆蓋操做。這就給了咱們一點提示,若是咱們真的不用去關心DUPLICATE KEY錯誤,並且但願作到覆蓋效果,那麼使用REPLACE真心不錯;若是不用關心DUPLICATE KEY錯誤,同時也不想要覆蓋,那麼INSERT IGNORE更好。
  • 傳統的INSERT-UPDATE方式真心慢,理解起來也不復雜,送過去-返回來-再送過去-再返回來。仍是改用INSERT-ON-DUPLICATE-KEY-UPDATE吧。
相關文章
相關標籤/搜索