批量插入數據之程序優化

最近遇到一個問題:我的程序需要向某張表中導入一萬條數據,如何提高其效率?

在代碼層面,下面兩種方式是比較常見的:

使用Statement對象

使用PreparedStatement對象

執行插入的代碼如下:

public void insertByStatement(String userName,String password){
		Connection conn=BaseDao.getInstance().getConnection();
		Statement statement=null;
		try {
			statement=conn.createStatement();
			String sql="insert into user_info (user_name,user_pass) values('"+userName+"',"+"'"+password+"')";
			int i=statement.executeUpdate(sql);
			if(i<=0){
				throw new SQLException("插入失敗!");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			BaseDao.getInstance().closeAll(null, statement, null);
		}
	}

	public void insertByPreparedStatement(String userName,String password){
		Connection conn=BaseDao.getInstance().getConnection();
		PreparedStatement ps=null;
		try {
			String sql="insert into user_info (user_name,user_pass) values(?,?)";
			ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
			for (int i = 0; i < 2500; i++) {
				ps.setString(1, userName);
				ps.setString(2, password);
				ps.addBatch();
			}
			ps.executeBatch();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			BaseDao.getInstance().closeAll(null, ps, null);
		}
	}


 

下面分爲單線程和多線程兩種思路來測試:

單線程情況:

使用statement耗時218s。

try {
			conn.setAutoCommit(false);

			for(int i=1;i<=10000;i++){
				new PostsDao().insertByStatement("test", "test");
			}
			conn.commit();
		} catch (SQLException e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}

 

使用preparedstatement批處理耗時8s。

		try {
			conn.setAutoCommit(false);

				new PostsDao().insertByPreparedStatement("lemon", "lemon");
			conn.commit();
		} catch (SQLException e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}



多線程(4個線程,每個線程插入2500條)情況下:

使用Statement耗時61s,本文略去代碼。

 

使用PreparedStatement批處理耗時4s,代碼如下:

try {
			conn.setAutoCommit(false);
			ThreadPoolExecutor threadPool2 = new ThreadPoolExecutor(4, 4, 0,
					TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
			threadPool2.execute(new ExecuteCallableThread());
			threadPool2.shutdown(); //關閉後不能加入新線程,隊列中的線程則依次執行完
			while(threadPool2.getPoolSize()!=0);
			System.out.println("main thread end!");
		} catch (SQLException e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}

 

本文僅僅在代碼層面做了優化,可以看出,在一次性大量地插入數據時,PreparedStatement對象的executeBatch()和多線程的效率是比較好的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章