ORA_HASH를 이용한 Partitioning 구현

2018. 12. 26. 00:39Spring Batch

반응형

ORA_HASH를 이용한 Partitioning 구현

오라클의 ORA_HASH를 이용하여서 구현하는 방법은 사용자가 설정한 gridSzie 만큼 분할하여서 HASH VALUES를

생성한다. 그리고 분할된 영역별로 병렬로 수행하는 방식이다.



- 사용자가 지정한 gridSize 만큼 Partition을 생성한다.

- 분할된 HASH 영역별로 Reader, Writer 작업을 수행한다.

- 위 그림에서 보면 조회된 테이블 결과에서 HASH_RANGE값은 0~gridSize 만큼 생긴다.



PartitionJob.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="partitionJob" xmlns="http://www.springframework.org/schema/batch">
		<step id="partitionStep">
			<!-- slave -->
			<partition step="masterPartition" partitioner="partioner">
				<handler grid-size="5" task-executor="taskExecutor"/>
			</partition>
		</step>
	</job>
	
	<!-- Partitioner BEAN 설정 -->
	<bean id="partioner" class="com.batchguide.partitioner.PartitionerHelper" />

	<!-- TaskExecutor BEAN 설정 -->
	<bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />

	<!-- READER, WIRTER 설정 -->
	<step id="masterPartition" xmlns="http://www.springframework.org/schema/batch">
		<tasklet>
			<chunk writer="blackFridayWriterPartition" reader="blackFridayReaderPartition" commit-interval="1000" />
		</tasklet>
	</step>
	
	<!-- Reader 설정 -->
	<bean id="blackFridayReaderPartition" class="org.mybatis.spring.batch.MyBatisCursorItemReader" scope="step">
		<!-- queryId 설정 -->
		<property name="queryId" value="selectBlackFridaysForOracle" />
		
		<!-- parameters 설정 -->
		<property name="parameterValues">
			<map>
				<entry key="parallelTotal" value="#{stepExecutionContext[parallelTotal]}"/>
				<entry key="parallelIndex" value="#{stepExecutionContext[parallelIndex]}"/>
			</map>
		</property>
		
		<!-- sqlSession -->
		<property name="sqlSessionFactory" ref="oracleSqlSession" />
	</bean>
	
	<!-- Writer 설정 -->
	<bean id="blackFridayWriterPartition" class="org.mybatis.spring.batch.MyBatisBatchItemWriter">
		<property name="statementId" value="insertBlackFridayForMySqlPartition" />
		<property name="sqlSessionTemplate" ref="batchMysqlSqlSessionTemplate" />
	</bean>
	
</beans>


PartitionerHelpler.java 작성


package com.batchguide.partitioner;

import java.util.HashMap;
import java.util.Map;

import org.springframework.batch.core.partition.support.Partitioner;
import org.springframework.batch.item.ExecutionContext;

public class PartitionerHelper implements Partitioner {
	
	@Override
	public Map partition(int gridSize) {
		
		HashMap result = new HashMap();
		
		for (int index = 0; index < gridSize; ++index) {
			ExecutionContext value = new ExecutionContext();
			value.putInt("parallelTotal", gridSize);
			value.putInt("parallelIndex", index);
			
			result.put("partition" + index, value);
		}
		
		return result;
		
	}

}

- ColumnRangePartitioner과는 다른 점은 사용자가 지정한 gridSize를 전체 병렬수행 프로세스수로 하고 그 수만큼

  루프를 돌면서 HASH_RANGE 값과 비교하면서 일치하는 블럭의 데이터를 읽어서 처리하도록 하는데 목적이 있다.



blackFridayReaderPartition 작성


OracleQuerySQL.xml 파일에 조회 쿼리 작성

<select id="selectBlackFridaysForOracle" resultType="com.batchguide.vo.BlackFridayVO">
<![CDATA[
	SELECT /* id:selectBlackFridaysForOracle| BlackFriday 데이터 조회 | OracleQuerySQL.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 MOD(ORA_HASH(USER_ID),#{parallelTotal,jdbcType=INTEGER})=#{parallelIndex,jdbcType=INTEGER}
]]>
</select>

- WHERE 조건절에서 ORA_HASH 값을 gridSize 만큼 나눈 나머지값이 HASH RAGE 값과 일치하는 영역의 데이터를

  조회한다.



blackFridayWriterPartition 작성


MySQLQuerySQL.xml 파일에 등록 쿼리 작성

<insert id="insertBlackFridayForMySqlPartition" parameterType="com.batchguide.vo.BlackFridayVO">
	insert /* id:insertBlackFridayForMySql| 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>



실행 및 테스트결과



- 위의 그림은 앞선 Column Range Partitioning과 마찬가지 결과 임을 확인 할 수 있다.



[소스레파지토리]

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


반응형

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

TASKLET 예제  (0) 2019.01.15
Range Partitioning 예제 - 구현  (0) 2018.12.18
Range Partitioning 예제 - 설정  (0) 2018.12.17
CompositeItemWriter 예제 - 구현  (0) 2018.12.02
CompositeItemWriter 예제 - 설정  (0) 2018.12.02