2018. 12. 26. 00:39ㆍSpring 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 Mappartition(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 |