JDBC Statement PrepareStateme和Batch性能小測

      今天在Javaeye論壇上看到有位網友得出結論:主題:Hibernate性能 - 30倍普通SQL操作 - 探討 地址:http://www.javaeye.com/topic/743613 .貼子中說JDBC測試插入10000條數據花費時間:Total spent 249531毫秒.而且貼子還說:這個時間我覺得是比較合理的執行一條SQL花費25毫秒左右,之前有關效率方面的測試和這個結果差不多。

      不知他在什麼配置情況下操作。因爲結果是4分多鐘。對於此結論很是驚奇,因爲以前做過數據同步的東西,於是馬上親自驗證,數據庫和測試參數和他的都一樣。

 

先說結果:我的測試最慢的只用了2.6秒。Statement最慢,PrepareStaement快了5秒鐘,Batch和PrepareStatement並沒有實質性的提高,只是一小點(這個倒是讓我奇怪)。從一萬到十萬數據量都做過測試,但變化不大。我一直認爲Batch會提高不少數量級的,可是結果讓我失望,也不知哪寫得不對,大家可以評點一下代碼。

------------------------------------------------------------
結果已出來,是默認的Mysql不是InnoDB,所以沒有事務,所以之前測的沒有本質變化。實際上在事務下,Batch能提高數量級的提高。

 

直接pringln 10000的一些對比數據:

清空表
普通的Statement插入數據:
插入數據量:10000
<運行時間: 2.656 秒>
運行時間:2656 毫秒
2.656
================================
清空表
通過PrepareStatement插入數據:
插入數據量:10000
<運行時間: 2.156 秒>
運行時間:2156 毫秒
2.156
================================
清空表
用批處理插入數據:
批量更新成功 10000 條記錄!
<運行時間: 2.078 秒>
運行時間:2078 毫秒
2.078
================================

 

代碼如下:

 

package test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

import com.fastbo.util.Clock;
import com.fastbo.util.ConnectionFactory;
import com.fastbo.util.DbUtil;

/**
 * Description: Jdbc相關性能測試,batch處理,PrepareStatement,Statement等。
 *
 * <p>
 * Mysql數據庫:表結構爲簡單的id,name(varchar:255),type(varchar:255)字段,id自增
 * </p>
 *
 * @author Peter Wei Email: <a href="mailto:[email protected]">[email protected] </a>
 *
 * @version 1.0 2010-8-21
 */
public class JdbcTest {

 /**
  * 測試數據量
  */
 public static int TEST_NUM = 10000;

 /**
  * 批處理大小
  */
 public static int BATCH_SIZE = 300;

 /**
  * 清空數據表
  *
  * @param con
  */
 public static void clear(Connection con) {
  PreparedStatement ps = null;
  StringBuffer buff = new StringBuffer();
  try {
   buff.append("truncate table bobo");
   ps = con.prepareStatement(buff.toString());
   ps.executeUpdate();
   System.out.println("清空表");
  } catch (SQLException e) {
   e.printStackTrace();
  } finally {
   DbUtil.close(ps);
  }
 }

 /**
  * 普通的Statement插入數據
  *
  * @param con
  */
 public static int add(Connection con) {
  Statement stmt = null;
  int num = 0;
  String sql = "insert into bobo(name,type) values('Peter Wei','test')";
  try {
   stmt = con.createStatement();
   for (int i = 0; i < TEST_NUM; i++) {
    num += stmt.executeUpdate(sql);
   }
   System.out.println("插入數據量:" + num);
  } catch (SQLException e) {
   e.printStackTrace();
  } finally {
   DbUtil.close(stmt);
  }
  return num;

 }

 /**
  * 用PrepareStatement插入數據
  *
  * @param con
  */
 public static void addByPrepareStatement(Connection con) {

  PreparedStatement ps = null;
  StringBuffer buff = new StringBuffer();
  int num = 0;
  try {
   buff.append("insert into bobo(name,type)");
   buff.append(" values(?,?)");
   ps = con.prepareStatement(buff.toString());
   for (int i = 0; i < TEST_NUM; i++) {
    int index = 1;
    ps.setString(index++, "Peter Wei");
    ps.setString(index++, "test");
    num += ps.executeUpdate();
   }
   System.out.println("插入數據量:" + num);
  } catch (SQLException e) {
   e.printStackTrace();
  } finally {
   DbUtil.close(ps);
  }
 }

 /**
  * 用批處理插入數據
  *
  * @param con
  */
 public static void addByBatch(Connection con) {
  PreparedStatement ps = null;
  StringBuffer buff = new StringBuffer();
  int sum = 0;
  int[] num = null;
  try {
   buff.append("insert into bobo(name,type) values(?,?)");

   con.setAutoCommit(false);
   ps = con.prepareStatement(buff.toString());
   for (int i = 0; i < TEST_NUM; i++) {
    int index = 1;
    ps.setString(index++, "Peter Wei");
    ps.setString(index++, "test");
    ps.addBatch();
    if (i != 0 && i % BATCH_SIZE == 0) {
     num = ps.executeBatch();
     sum += num.length;
     con.commit();
     // System.out.println("batch:" + i);
    }

   }
   num = ps.executeBatch();
   sum += num.length;
   con.commit();
   con.setAutoCommit(true);
   System.out.println("批量更新成功 " + sum + " 條記錄!");
  } catch (SQLException e) {
   e.printStackTrace();
  } finally {
   DbUtil.close(ps);
  }
 }

 public static void main(String[] args) {
  Connection con = ConnectionFactory.getConnection();
  clear(con);
  Clock c = new Clock();
  // 普通的Statement插入數據
  System.out.println("普通的Statement插入數據:");
  c.start();
  add(con);
  c.stop();
  System.out.println(c.toString());
  c.readMilli();
  System.out.println(c.read());
  System.out.println("================================");

  clear(con);
  // 通過PrepareStatement插入數據
  System.out.println("通過PrepareStatement插入數據:");
  c = new Clock();
  c.start();
  addByPrepareStatement(con);
  c.stop();
  System.out.println(c.toString());
  c.readMilli();
  System.out.println(c.read());
  System.out.println("================================");

  clear(con);
  // 用批處理插入數據
  System.out.println("用批處理插入數據:");
  c = new Clock();
  c.start();
  addByBatch(con);
  c.stop();
  System.out.println(c.toString());
  c.readMilli();
  System.out.println(c.read());
  System.out.println("================================");

 }

}

發佈了29 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章