您的位置:首页 > 数据库 > MySQL

mysql批量insert数据的几种方法的效率比较

2013-12-31 21:53 218 查看
最近做shopsping爬虫优化时,得出几点关于批量insert数据及各自的效率的心得

语言:java

效率衡量参数:多次执行,比较各自的执行时间

测试数据量:1W条

mysql驱动版本:5.1.24

下面是代码,其中有共用的一个获取链接的函数

public class CreatConnection {

// private static String url = "jdbc:mysql://192.168.0.205:3306/test1";

private static String url = "jdbc:mysql://192.168.0.205:3306/test1?rewriteBatchedStatements=true";

private static String username = "root";

private static String password = "root";

private static Connection con = null;
public static Connection getConnection() throws SQLException {
try {
Class.forName("com.mysql.jdbc.Driver");
con = (Connection) DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
}


1.第一种: for循环,每次循环执行一次操作

代码如下:

public class TestAddBatch {

public static void main(String[] args) { 

Long startTime = System.currentTimeMillis();

System.out.println();

System.out.println(new SimpleDateFormat("yyyy-M-dd HH:mm:ss")

.format(startTime) + "\r\n start");

try {

String sql =""; 

Connection conn = CreatConnection.getConnection();

PreparedStatement pre = null;

sql = "INSERT INTO stu(name,content) values(?,?)"; 

pre = conn.prepareStatement(sql);

for (int i = 0; i < 100000; i++) {

pre.setString(1, "xiaoxiao_"+String.valueOf(i));

pre.setString(2, "liu"); 

pre.executeUpdate();

}

Long endTime = System.currentTimeMillis();

System.out.println();

System.out.println(new SimpleDateFormat("yyyy-M-dd HH:mm:ss")

.format(endTime) + "\r\n end");

System.out.println("Cost Time:"+(endTime-startTime));

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

暂且不测试1W条数据,单测试100条,就耗时3797ms;1000条,耗时43471ms. 1W条数据时,耗时405060ms(6.7分钟),可见这种方法效率比较低

该方法总结:此种方法效率极低,当要执行批量操作时不建议采用这种方法。

2. 第二种:采用insert into tableName Values(),(),()形式

代码如下:

public class TestInsertValues {

public static void main(String[] args) {

Long startTime = System.currentTimeMillis();

ArrayList<stu> stu = new ArrayList();

for(int i = 0;i < 100000;i +){//测试不同数据量,只需在这里修改

stu.add(new stu("xiaoxiao_"+String.valueOf(i),"liu")); 

}

System.out.println(new SimpleDateFormat("yyyy-M-dd HH:mm:ss")

.format(startTime) + "\r\n start");

String sql =null;

sql = "INSERT INTO stu(name,content) VALUES";

for(int j = 0;j < stu.size(); j+){

stu su = stu.get(j);

if(j ==stu.size()-1){

sql = sql+ "(?,?)";

}

else{

sql = sql+ "(?,?),";

}



try {

Connection conn = CreatConnection.getConnection();

PreparedStatement pre = null;

pre = conn.prepareStatement(sql);

for(int i= 0;i<stu.size();i++){

pre.setString(i*2+1, stu.get(i).getName()); 

pre.setString(i*2+2, stu.get(i).getContent()); 

}

if (pre != null) {

pre.executeUpdate();

pre.close();

}

Long endTime = System.currentTimeMillis();

System.out.println();

System.out.println(new SimpleDateFormat("yyyy-M-dd HH:mm:ss")

.format(endTime) + "\r\n end");

System.out.println("Cost Time:"+(endTime-startTime)+"ms");

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

测试1W条数据,耗时1216ms,1469ms,1579ms 平均值1421ms

测试10W条数据,耗时28406ms,28781ms,28459ms,28919ms,28987ms 平均值28710ms

注意:这里用insertvalues数据量过大的时候,有可能会报一个错误“写入数据量过大”,需要修改配置文件。默认的配置文件中是允许最大的数据量是1M,配置文件在MySQL安装目录下的

my.ini文件中的[mysqld]段中的"max_allowed_packet = 1M",(可能有些文件会没有这一行的)

格式为:

[mysqld]

max_allowed_packet = 1M (将1M更改为4M(如果没有这行内容,增加一行)),保存,重起MySQL服务。

3. 第三种:采用preparedStatement的addBatch和executeBatch方法

此时需要注意:

1)将获取连接中的URL参数改为如下的形式:private static String url = "jdbc:mysql://192.168.0.205:3306/test1?rewriteBatchedStatements=true";

2)在代码中添加conn.setAutoCommit(false); 保证addBatch的时候,不会自动提交执行,最后conn.commit();

代码如下:

public class TestAddBatch { 

public static void main(String[] args) {

// TODO Auto-generated method stub

int[] count = null;

Long startTime = System.currentTimeMillis();

System.out.println();

System.out.println(new SimpleDateFormat("yyyy-M-dd HH:mm:ss")

.format(startTime) + "\r\n start");

try {

String sql =""; 

Connection conn = CreatConnection.getConnection();

conn.setAutoCommit(false); 

PreparedStatement pre = null;

sql = "INSERT INTO stu(name,content) values(?,?)"; 

pre = conn.prepareStatement(sql);

for (int i = 0; i < 10000; i++) {

pre.setString(1, "xiaoxiao_"+String.valueOf(i));

pre.setString(2, "liu"); 

pre.addBatch(); 

}

if (pre != null) {

count = pre.executeBatch();

conn.commit();

pre.close();

}

Long endTime = System.currentTimeMillis();

System.out.println();

System.out.println(new SimpleDateFormat("yyyy-M-dd HH:mm:ss")

.format(endTime) + "\r\n end");

System.out.println("Cost Time:"+(endTime-startTime));

} catch (SQLException e) { 

e.printStackTrace();

}

}

}

测试1W条数据,1317ms,942ms,903ms 平均值1054ms

测试10W条数据,3824ms,6887ms,5672ms,6406ms,4390ms 平均值:5435ms

综上:采用preparedStatement的addBatch和executeBatch的方法效率是最高的,才操作也更为简便。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息