Mysql批量插入數據問題解決和優化
一、問題描述
項目中mysql批量插入大概50000左右數據,使用事務和批量,但是速度依舊很慢,大約60s左右,迫切希望改進這個問題。
二、問題原因
儘管是批量addBatch()但是,mysql卻默認沒有執行批量,時間還是一條一條添加導致速度非常慢。解決辦法:鏈接mysql字符串添加 rewriteBatchedStatements=true
三、解決和驗證
1.測試代碼
(1)新建測試表語句
create table mysqltest(
id INT,
name char(10)
)
create table mysqltest1(
id INT,
name char(10)
)
(2)Mysql鏈接工廠類
package bulk.mysql;
import java.sql.Connection;
import java.sql.DriverManager;
public class MySQLConnections {
private String driver = "";
private String dbURL = "";
private String user = "";
private String password = "";
private static MySQLConnections connection = null;
private MySQLConnections() throws Exception {
driver = "com.mysql.jdbc.Driver";
dbURL = "jdbc:mysql://ip:3306/test?rewriteBatchedStatements=true";
user = "root";
password = "passwd";
System.out.println("dbURL:" + dbURL);
}
public static Connection getConnection() {
Connection conn = null;
if (connection == null) {
try {
connection = new MySQLConnections();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
try {
Class.forName(connection.driver);
conn = DriverManager.getConnection(connection.dbURL,
connection.user, connection.password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
}
(3)Mysql更新類
package bulk.mysql;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class MySQLUpdate {
static Connection con = MySQLConnections.getConnection();
static PreparedStatement stmt = null;
public static int executeInsert() throws SQLException {
int i = 0;
//設置批量處理的數量
int batchSize = 5000;
stmt = con.prepareStatement("insert into mysqltest (id,name) "
+ "values (?,?)");
// 關閉事務自動提交 ,這一行必須加上
con.setAutoCommit(false);
for (int j = 0; j < 50005; j++){
++i;
stmt.setInt(1, j);
stmt.setString(2, "name");
stmt.addBatch();
if ( i % batchSize == 0 ) {
stmt.executeBatch();
con.commit();
}
}
if ( i % batchSize != 0 ) {
stmt.executeBatch();
con.commit();
}
return i;
}
public static void executeInsert2() throws SQLException {
// 關閉事務自動提交 ,這一行必須加上
con.setAutoCommit(false);
stmt = con.prepareStatement("insert into mysqltest (id,name) "
+ "values (?,?)");
for (int j = 0; j < 50002; j++){
stmt.setInt(1, j);
stmt.setString(2, "name");
stmt.addBatch();
}
stmt.executeBatch();
con.commit();
stmt.close();
con.close();
}
}
(4)Mysql測試類
package bulk.mysql;
import java.sql.SQLException;
public class Test {
public static void main(String[] args) throws SQLException {
long begin1 = System.currentTimeMillis();
MySQLUpdate.executeInsert();
long end1 = System.currentTimeMillis();
System.out.println("程序運行時間爲:" + (end1 - begin1));
long begin2 = System.currentTimeMillis();
MySQLUpdate.executeInsert2();
long end2 = System.currentTimeMillis();
System.out.println("程序運行時間爲:" + (end2 - begin2));
}
}
2.測試鏈接字符串不同配置
(1)爲dbURL = “jdbc:mysql://ip:3306/test”;時
運行結果
程序測試插入時間
程序運行時間爲:62095
程序運行時間爲:60129
(2)爲dbURL = “jdbc:mysql://ip:3306/test?rewriteBatchedStatements=true”;時
運行結果
程序運行時間爲:2181
程序運行時間爲:419
3.結論
優化了一百倍左右,這個真的很誇張了,而且確認最好一次性提交