본문 바로가기
WEB/JSP

트랜잭션 처리, 배치 처리

by 둥바 2022. 7. 22.

배치처리 ( 일괄 처리 )

: 대량의 DML작업 시 일반작업과 배치처리한 작업과의 처리시간에 차이가 존재

ex) 고지서 일괄적으로 처리

: JDBC는 기본으로 auto commit되어 있으나, 대량의 DML의 경우 수동 commit으로 변경하여 진행

 

CREATE TABLE EMP (  --test_data.sql에서    발췌
EMPNO NUMBER(4, 0), ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4, 0), HIREDATE DATE, 
SAL NUMBER(7, 2), COMM NUMBER(7, 2), DEPTNO NUMBER(2, 0)
);
insert into emp values (7369,'김철수','사원',7902,'2000-12-17',200,null,20);
insert into emp values (7499,'이찬수','주임',7698,'2001-02-20',260,300,30);
insert into emp values (7521,'박종수','주임',7698,'2002-02-22',325,500,30);
insert into emp values (7566,'임채호','과장',7839,'2001-04-02',497,null,20);
select * from emp;
desc emp; --컬럼    구조   보기
--테이블 복사(레코드는 복사되지 않음), 1=0은 false를 의미 
create table emp2 as select * from emp where 1=0;
alter table emp2 modify empno number(10);
alter table emp2 modify ename varchar2(20);
alter table emp2 modify deptno number(10); commit;
select count(*) from emp2; ----트랜잭션 처리완료 후 확인

 

이클립스에서 src/main/java 밑에 emp 폴더를 만들고, EmpDAO 클래스를 만든다.

 

 

package emp;

import java.sql.Connection;
import java.sql.PreparedStatement;

import config.DB;

public class EmpDAO {
	public void insert() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			conn = DB.getConn();
			conn.setAutoCommit(false);//auto commit 해제
			long before=System.currentTimeMillis();//실행 전 시간 처리
			for(int i=1;i<=100000;i++) {
				//고객에게 10만건의 SMS를 돌린다면
				String sql = "insert into emp2 (empno,ename,deptno) values (?,?,?)";
				pstmt=conn.prepareStatement(sql);
				pstmt.setInt(1, i);//number
				pstmt.setString(2, "kim"+i);//varchar2
				pstmt.setInt(3, i);//number
				pstmt.executeUpdate();//select 제외
				pstmt.close();
			}
			long after=System.currentTimeMillis();//실행 후 시간 처리
			conn.commit();//수동 commit
			conn.setAutoCommit(true);//다음 작업을 위해서 true로 다시 설정
			System.out.println("실행시간" + (after-before));
		} catch (Exception e) {
			e.printStackTrace();
			try {
				//문제가 생겼다면 롤백해라.
				if(conn!= null) conn.rollback();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		} finally {
			try {
				if(pstmt != null) pstmt.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			try {
				if(conn != null) conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
}

 

 

프론트 엔드 단을 만들어 준다. transaction.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="emp.EmpDAO"  %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>transaction.jsp</title>
<script src=../include/jquery-3.6.0.min.js></script>
</head>
<body>
<%
EmpDAO dao = new EmpDAO();
dao.insert();
%>
</body>
</html>

 

실행시간78788 콘솔에 출력됨

 

이번에는 배치 처리(일괄작업)을 진행해보자.

 

package emp;

import java.sql.Connection;
import java.sql.PreparedStatement;

import config.DB;

public class EmpDAO {
	public void insert() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			conn = DB.getConn();
			conn.setAutoCommit(false);//auto commit 해제
			long before=System.currentTimeMillis();//실행 전 시간 처리
			for(int i=1;i<=100000;i++) {
				//고객에게 10만건의 SMS를 돌린다면
				String sql = "insert into emp2 (empno,ename,deptno) values (?,?,?)";
				pstmt=conn.prepareStatement(sql);
				pstmt.setInt(1, i);//number
				pstmt.setString(2, "kim"+i);//varchar2
				pstmt.setInt(3, i);//number
				pstmt.executeUpdate();//select 제외
				pstmt.close();
			}
			long after=System.currentTimeMillis();//실행 후 시간 처리
			conn.commit();//수동 commit
			conn.setAutoCommit(true);//다음 작업을 위해서 true로 다시 설정
			System.out.println("실행시간" + (after-before));
		} catch (Exception e) {
			e.printStackTrace();
			try {
				//문제가 생겼다면 롤백해라.
				if(conn!= null) conn.rollback();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		} finally {
			try {
				if(pstmt != null) pstmt.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			try {
				if(conn != null) conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}//end insert
	
	//배치작업
	public void insert_batch() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			conn = DB.getConn();
			conn.setAutoCommit(false);//auto commit 해제
			String sql = "insert into emp2 (empno,ename,deptno) values (?,?,?)";
			pstmt=conn.prepareStatement(sql);
			long before=System.currentTimeMillis();//실행 전 시간 처리
			for(int i=100001;i<=200000;i++) {
				//고객에게 10만건의 SMS를 돌린다면
				pstmt.setInt(1, i);//number
				pstmt.setString(2, "lee"+i);//varchar2
				pstmt.setInt(3, i);//number
				pstmt.addBatch();//일괄처리 작업 예약	
			}
			pstmt.executeBatch();//일괄처리작업 실행
			long after=System.currentTimeMillis();//실행 후 시간 처리
			conn.commit();//수동 commit
			conn.setAutoCommit(true);//다음 작업을 위해서 true로 다시 설정
			System.out.println("실행시간" + (after-before));
		} catch (Exception e) {
			e.printStackTrace();
			try {
				//문제가 생겼다면 롤백해라.
				if(conn!= null) conn.rollback();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		} finally {
			try {
				if(pstmt != null) pstmt.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			try {
				if(conn != null) conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
}

 

배치 처리 메소드 jsp에 추가

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="emp.EmpDAO"  %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>transaction.jsp</title>
<script src=../include/jquery-3.6.0.min.js></script>
</head>
<body>
<%
EmpDAO dao = new EmpDAO();
//dao.insert();
dao.insert_batch();//배치처리 메소드 호출
%>
</body>
</html>

 

실행시간 2097

 

즉, 일반 실행과 배치처리에 엄청난 시간 차이가 난다.