方法一:Statement使用如下
import java.sql.*;
public class InsertMoreStatement {
// MySQL 8.0 以上版本 - JDBC 驅動名及數據庫 URL
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3308/weqqq?useSSL=false&serverTimezone=UTC&useLocalSessionState=true";
// 數據庫的用戶名與密碼,需要根據自己的設置
static final String USER = "root";
static final String PASS = "root";
public static void main(String[] args) {
Connection con = null;
try {
con = DriverManager.getConnection(DB_URL,USER,PASS);
Statement statement = (Statement)con.createStatement();
con.setAutoCommit(false);
long startTime = System.currentTimeMillis();
System.out.println("開始……");
for (int i=0;i<1000000;i++)
{
statement.execute(String.format("INSERT INTO `pi_liang_insert`(value) VALUES ( '%s');" , "lt_"+ i));
}
long endTime = System.currentTimeMillis();
con.commit();
System.out.println("用時:" + (endTime-startTime));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
調用結果
用時接近4分鐘
我們可以查看日誌。其過程爲將插入命令調用100萬次
注意 url裏的 useLocalSessionState=true,該參數設置爲true可提高很多速率,否則每條插入語句前都會有一句狀態確認的查詢,如下圖
因爲以上方法效率趕人,故在批量插入時並不推薦
方法二PreparedStatement:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
public class InsertMorePreparedStatement {
// MySQL 8.0 以下版本 - JDBC 驅動名及數據庫 URL
// static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
// static final String DB_URL = "jdbc:mysql://localhost:3308/RUNOOB";
// MySQL 8.0 以上版本 - JDBC 驅動名及數據庫 URL
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3308/weqqq?useSSL=false&serverTimezone=UTC&useLocalSessionState=true&rewriteBatchedStatements=true";
// 數據庫的用戶名與密碼,需要根據自己的設置
static final String USER = "root";
static final String PASS = "root";
static String sql = "INSERT INTO `pi_liang_insert`(value) VALUES ( ?)";
public static void main(String[] args) {
Connection con = null;
try {
con = DriverManager.getConnection(DB_URL,USER,PASS);
PreparedStatement preparedStatement = con.prepareStatement(sql);
con.setAutoCommit(false);
long startTime = System.currentTimeMillis();
System.out.println("開始……");
// for (int i=0;i<100000;i++)
// {
// preparedStatement.setString(1,"asfsdfsdf"+i);
// preparedStatement.addBatch();
// }
// preparedStatement.executeBatch();
for (int j=0;j<100;j++)//防止最大命令字符數溢出
{
for (int i=0;i<10000;i++)
{
preparedStatement.setString(1,"lt_"+(i+j*10000));
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
}
long endTime = System.currentTimeMillis();
con.commit();
System.out.println("用時:" + (endTime-startTime) + "毫秒");
}
catch (Exception e)
{
e.printStackTrace();
}
System.exit(0);
}
}
調用結果如下:
百萬數據插入僅需要6.8秒。
我們來看下日誌
插入命令變爲 批量插入語法:
INSERT INTO `pi_liang_insert`(value) VALUES ( 'xxxxxxx'),('xxxxxxxx')………………
不再逐條插入,故速率提升。
在這個裏我分100次,一次提交10000條數據,主要是因爲,命令的字節包有長度限制。如果字節包長度過大,可修改數據庫裏的參數
查看max_allowed_packet:
mysql> show variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 15728640 |
+--------------------+----------+
修改max_allowed_packet:
mysql> set global max_allowed_packet=1024*10;
注意rewriteBatchedStatements必須設置爲ture,否則依然是逐條插入