Range Partitioning 예제 - 구현

2018. 12. 18. 00:13Spring Batch

반응형

Range Partitioning 구현

앞에서 설정한 설정 정보를 이용하여 실제로 예제를 구현해보도록 하자. 입력 데이터는 MySQL 테이블에 등록 해두었고 이 데이터를 Oracle 테이블에 등록 해보도록 하자.

 

구현에 앞서 프로그램 전체적인 구조는 아래 그림을 참고 하도록 하자.

- 전체적인 구조는 사용자가 지정한 grid-size 만큼 작업을 분할한다. 예제에서는 5로 설정 하였다. 따라서 위의

  그림을 보면 5개의 Slave가 생성된다.

- 앞에서 작성한 ColumnRangePartitioner 클래스를 이용하여서 minValue와 maxValue를 구한다.

- 그리고 Slave 별로 Reader, Writer 작업을 수행한다.  

 

 

RangePartitionJob.xml 작성


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/batch
						http://www.springframework.org/schema/batch/spring-batch.xsd">
						
	<description>
	<![CDATA[
	이 예제는 대용량 데이터 처리 시 작업을 분할 하여 처리하는 Partitioner 예제이다.
	]]>
	</description>
						
	<job id="rangePartitionJob" xmlns="http://www.springframework.org/schema/batch">
		<step id="rangePartitionStep">
			<!-- slave -->
			<partition step="masterRangePartition" partitioner="rangePartioner">
				<handler grid-size="5" task-executor="taskExecutor"/>
			</partition>
		</step>
	</job>
	
	<!-- Column Partition 설정 -->
	<bean id="rangePartioner" class="com.batchguide.partitioner.ColumnRangePartitioner">
		<property name="dataSource" ref="mysqlDataSource" />
		<property name="table" value="black_friday" />
		<property name="column" value="user_id" />
	</bean>

	<bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />

	<!-- READER, WIRTER 설정 -->
	<step id="masterRangePartition" xmlns="http://www.springframework.org/schema/batch">
		<tasklet>
			<chunk writer="blackFridayWriter" reader="blackFridayReader" commit-interval="1000" />
		</tasklet>
	</step>
	
	<!-- Reader 설정 -->
	<bean id="blackFridayReader" class="org.mybatis.spring.batch.MyBatisCursorItemReader" scope="step">
		<!-- queryId 설정 -->
		<property name="queryId" value="selectBlackFridays" />
		
		<!-- parameters 설정 -->
		<property name="parameterValues">
			<map>
				<entry key="minId" value="#{stepExecutionContext[minValue]}"/>
				<entry key="maxId" value="#{stepExecutionContext[maxValue]}"/>
			</map>
		</property>
		
		<!-- sqlSession -->
		<property name="sqlSessionFactory" ref="mysqlSqlSession" />
	</bean>
	
	<!-- Writer 설정 -->
	<bean id="blackFridayWriter" class="org.mybatis.spring.batch.MyBatisBatchItemWriter">
		<property name="statementId" value="insertBlackFridayForOracle" />
		<property name="sqlSessionTemplate" ref="batchOracleSqlSessionTemplate" />
	</bean>
	
	
</beans>

 

- 분할할 작업수를 grid-size를 통해서 설정한다.

- 분할정보를 설정하기 위해 데이터소스, 테이블명, 컬럼명을 ColumnRangePartitioner 에 전달

- 분할된 정보를 이용하여 Reader/Writer 작업 수행

 

 

blackFridayReader 작성


MySQLQuery.xml 파일에 아래 쿼리를 작성한다.

파라미터정보는 minId, maxId를 넘겨주는데 이 값은 ColumnRangePartitioner에서 구한 minValue와 maxValue이다.

<select id="selectBlackFridays" resultType="com.batchguide.vo.BlackFridayVO">
<![CDATA[
	select /* id:selectBlackFridays| BlackFriday 데이터 조회 | MySQLQuerySQL.xml */
		   user_id
		 , product_id
		 , gender
		 , age
		 , occupation
		 , city_category
		 , stay_in_current_city_years
		 , marital_status
		 , product_category_1
		 , product_category_2
		 , product_category_3
		 , purchase
	  from black_friday 
	 where user_id >= #{minId} and user_id <= #{maxId}
]]>
</select>

 

blackFridayWriter 작성


OracleSQLQuery.xml 파일에 아래 쿼리를 작성한다.

 

<insert id="insertBlackFridayForOracle" parameterType="com.batchguide.vo.BlackFridayVO">
	insert /* id:insertBlackFridayForOracle| BlackFriday 데이터 저장 | MySQLQuerySQL.xml */ 
	  into black_friday 
		   (user_id
		  , product_id
		  , gender
		  , age
		  , occupation
		  , city_category
		  , stay_in_current_city_years
		  , marital_status
		  , product_category_1
		  , product_category_2
		  , product_category_3
		  , purchase)
	values (#{userId}
		  , #{productId}
		  , #{gender}
		  , #{age}
		  , #{occupation}
		  , #{cityCategory}
		  , #{stayInCurrentCityYears}
		  , #{maritalStatus}
		  , #{productCategory1}
		  , #{productCategory2}
		  , #{productCategory3} 
		  , #{purchase})
</insert>

 

BlackFridayVO 작성


조회결과는 담는 클래스

package com.batchguide.vo;

public class BlackFridayVO {

	private String userId;
	
	private String productId;
	
	private String gender;
	
	private String age;
	
	private String occupation;
	
	private String cityCategory;
	
	private String stayInCurrentCityYears;
	
	private String maritalStatus;
	
	private String productCategory1;
	
	private String productCategory2;
	
	private String productCategory3;
	
	private String purchase;

	/**
	 * @return the userId
	 */
	public String getUserId() {
		return userId;
	}

	/**
	 * @param userId the userId to set
	 */
	public void setUserId(String userId) {
		this.userId = userId;
	}

	/**
	 * @return the productId
	 */
	public String getProductId() {
		return productId;
	}

	/**
	 * @param productId the productId to set
	 */
	public void setProductId(String productId) {
		this.productId = productId;
	}

	/**
	 * @return the gender
	 */
	public String getGender() {
		return gender;
	}

	/**
	 * @param gender the gender to set
	 */
	public void setGender(String gender) {
		this.gender = gender;
	}

	/**
	 * @return the age
	 */
	public String getAge() {
		return age;
	}

	/**
	 * @param age the age to set
	 */
	public void setAge(String age) {
		this.age = age;
	}

	/**
	 * @return the occupation
	 */
	public String getOccupation() {
		return occupation;
	}

	/**
	 * @param occupation the occupation to set
	 */
	public void setOccupation(String occupation) {
		this.occupation = occupation;
	}

	/**
	 * @return the cityCategory
	 */
	public String getCityCategory() {
		return cityCategory;
	}

	/**
	 * @param cityCategory the cityCategory to set
	 */
	public void setCityCategory(String cityCategory) {
		this.cityCategory = cityCategory;
	}

	/**
	 * @return the stayInCurrentCityYears
	 */
	public String getStayInCurrentCityYears() {
		return stayInCurrentCityYears;
	}

	/**
	 * @param stayInCurrentCityYears the stayInCurrentCityYears to set
	 */
	public void setStayInCurrentCityYears(String stayInCurrentCityYears) {
		this.stayInCurrentCityYears = stayInCurrentCityYears;
	}

	/**
	 * @return the maritalStatus
	 */
	public String getMaritalStatus() {
		return maritalStatus;
	}

	/**
	 * @param maritalStatus the maritalStatus to set
	 */
	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

	/**
	 * @return the productCategory1
	 */
	public String getProductCategory1() {
		return productCategory1;
	}

	/**
	 * @param productCategory1 the productCategory1 to set
	 */
	public void setProductCategory1(String productCategory1) {
		this.productCategory1 = productCategory1;
	}

	/**
	 * @return the productCategory2
	 */
	public String getProductCategory2() {
		return productCategory2;
	}

	/**
	 * @param productCategory2 the productCategory2 to set
	 */
	public void setProductCategory2(String productCategory2) {
		this.productCategory2 = productCategory2;
	}

	/**
	 * @return the productCategory3
	 */
	public String getProductCategory3() {
		return productCategory3;
	}

	/**
	 * @param productCategory33 the productCategory3 to set
	 */
	public void setProductCategory3(String productCategory3) {
		this.productCategory3 = productCategory3;
	}

	/**
	 * @return the purchase
	 */
	public String getPurchase() {
		return purchase;
	}

	/**
	 * @param purchase the purchase to set
	 */
	public void setPurchase(String purchase) {
		this.purchase = purchase;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "BlackFridayVO [userId=" + userId + ", productId=" + productId + ", gender=" + gender + ", age=" + age
				+ ", occupation=" + occupation + ", cityCategory=" + cityCategory + ", stayInCurrentCityYears="
				+ stayInCurrentCityYears + ", maritalStatus=" + maritalStatus + ", productCategory1=" + productCategory1
				+ ", productCategory2=" + productCategory2 + ", productCategory3=" + productCategory3 + ", purchase="
				+ purchase + "]";
	}
}

 

실행 및 테스트결과


실행 후 결과를 보면 아래와 같다.

 

- 결과를 보면 총 5개의 작업이 분할 된 것을 확인 할 수 있으며 총 3,225,462 건이 등록 되었으며 5개의 작업에 건수

  가 분할 되어서 처리된것을 볼수 있다.

  작업시간은 약 4분 정도 소요 되었다.

 

 

[소스레파지토리]

☞ https://github.com/roopy1210/springbatch/blob/master/spring_batch_tutorial

 

 

반응형

'Spring Batch' 카테고리의 다른 글

TASKLET 예제  (0) 2019.01.15
ORA_HASH를 이용한 Partitioning 구현  (1) 2018.12.26
Range Partitioning 예제 - 설정  (0) 2018.12.17
CompositeItemWriter 예제 - 구현  (0) 2018.12.02
CompositeItemWriter 예제 - 설정  (0) 2018.12.02