1. 程式人生 > >Mybatis+mysql批量插入效能分析測試

Mybatis+mysql批量插入效能分析測試

前言

今天在網上看到一篇文章(後文中的文章指的就是它)
https://www.jianshu.com/p/cce617be9f9e
發現了一種有關於mybatis批量插入的新方法,而且看了文章發現我原來的方法好像有點問題,但是由於文章中使用的環境是sqlserver而我經常使用的是mysql所以還是需要親自來試試。

 

環境說明

專案使用springboot mybatis
資料庫mysql5.7
使用本地mysql所以網路可以忽略不計
插入物件完全相同,只有id自增

表結構如下:
CREATE TABLE order_test_tab (
id int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
order_id

varchar(20) NOT NULL COMMENT '訂單號',
order_name varchar(100) NOT NULL COMMENT '訂單名稱',
order_status int(1) NOT NULL COMMENT '訂單狀態',
order_content varchar(255) NOT NULL COMMENT '訂單說明',
add_time datetime NOT NULL COMMENT '訂單時間',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='測試訂單表';

 

方法說明

我使用了和文章中提到的一樣,三種方法進行測試


方法一:
使用for迴圈呼叫單條插入

方法二:
在sql中使用foreach進行批量insert

方法三:
使用mybatis的批量插入

 

結果說明

插入條數 100 500 1000 5000 100000
使用for迴圈插入 139ms 545ms 839ms 2629ms 31157ms
使用sql foreach插入 55ms 119ms 123ms 329ms 報錯
使用批量執行插入 48ms 111ms 239ms 1081ms 19235ms

其中報錯是因為sql長度過長超過了max_allowed_packet導致的,報錯資訊如下:
Error updating database. Cause: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large (22,700,108 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.

從結果我們顯然可以看出,使用第二種方式(使用sql foreach插入)效率最高,明顯與文章中差距很大,所以mysql和sqlserver還是有很大區別的,估計mysql針對批量插入的語句有過優化

 

測試說明

1.測試具體插入之前,首先執行刪除表中所有資料操作,一個是保證環境完全一致,一個是為了減少第一次連線資料庫所帶來的效能消耗。
2.執行時間的計算就是在執行sql的前後,建立物件的時間不計算在這之內
3.在使用本地mysql測試完成之後,使用外網伺服器的mysql進行測試,測試結果基本一致,時間都略有延長
4.測試程式碼在:https://github.com/LinkinStars/springBootTemplate/tree/test-batch-insert
其中包含order字樣的為測試相關程式碼,別的是無關程式碼,入口在test包下的OrderTest.java

 

結論

批量插入時還是使用sql foreach插入來的效率最高,因為它是整一條sql在執行所以當插入條數很多的時候會出現異常,所以使用這種方式時一定要主動限制插入的最大條數,不然容易出現異常,因為max_allowed_packet即使再大也會有不夠用的時候。
同時我們也應該竟可能去避免使用for迴圈插入資料,因為效能真的很差。