6장 실행 계획 ( 6.1 개요 )

RealMysql 2012.10.19 18:14 posted by dev.bistro


* 지은이의 말

  사람들이 NoSQL에 상당한 관심을 가지고 있지만, 실제로는 몽고DB나 카산드라같이 유명한하고 사용처는 많지 않다. 사용하더라도, 성능에 대해 괴로움이 많다고 한다.

  지은이도 관심을 가지는 Hbase를 포함한 NoSQL은 INSERT,UPDATE 쓰기 동작이 빠르지만, MySQL의 SELECT 조회처럼 퍼모먼스를 내긴 어렵다. 이처럼 명백하게 나뉜다.



* 초급 내용

  6장, 7장, 8장, 9장, 11장, 13장, 14장, 15장, 16장




6장. 실행계획


6.1 개요


6.1.1 쿼리 실행 절차

 MySQL 실행되는 과정

  1. SQL파싱 단계 : SQL문장을 잘게 쪼개 MySQL이 이해할 수 있는 수준으로 분리 

     MySQL 파서 모듈이 수행한다

     문법 오류는 여기서 걸러지고. SQL파스트리가 생성된다.

  

  2. 최적화 및 실행 계획 수립 단계 : SQL의 파스트리를 확인하면서 어떤 테이블, 어떤 인덱스를 쓸지 선택.

     MySQL 옵티마이저가 수행한다.

     연산의 단순화 및  사용 테이블, 사용 인덱스 결정  임시 테이블의 사용유무 체크 등등


  3. 결정된 테이블, 인덱스를 이용해 데이터를 가져온다.


6.1.2 옵티마이저 종류

 1. 비용기반 최적화(Cost-based optimizer , CBO) : 현제 대부분의 DBMS가 선택

    여러 실행 계획 수립, 예측을 통해 계획별 비용을 산출 최소 비용이 소요되는 방식을 선택한다.


 2. 규칙기반 최적화(Rule-based optimizer, RBO) : 예전 오라클

    대상 테이블의 크기, 선택도등 고려하지 않음

    옵티마이저 내부 규칙에 따라 실행 계획 수립 -> 같은 쿼리는 거의 같은 실행 방법을 만든다.


6.1.3 통계정보

    통계정보는 비용기반 최적화(CBO) 에서 가장 중요한것이다.

    MySQL의 통계정보는 다른DBMS보다 다양하지 않다. 기본적으로 레코드건수, 인덱스의 유니크 수 정도 (오라클의 통계 정보는 방대해서 따로 백업하기도 한다)

    


    레코드건수가 많지 않으면 통계 정보가 부정확한 경우가 많으므로 "ANALYZE"명령을 이용해 강제적으로 통계 정보를 갱신할 때도 있다. 


    통계정보 확인

     MyISAM : SHOW TABLE STATUS LIKE 'tb_test'\G

     InnoDB : SHOW INDEX FROM tb_test

    통계정보 갱신

     일반 테이블 통계 정보 수집 : ANALYZE TABLE tb_test;

     특정 파티션의 통계 정보 수집 : ALTER TABLE tb_test ANALYZE PARTITION p3;

    ANALYZE실행중

     MyISAM : 읽기 가능, 쓰기 불가능   // 전체 스캔 많인 시간이 소요 

     InnODB : 읽기, 쓰기 모두 불가능 (즉 서비스 도중에는 ANALYZE를 수행하지 마라) // 인덱스 페이지중 8개 정도만 랜덤 선택 분석하고 인덱스의 통계 정보로 갱신 (5.1.38이후는 셋팅가능)


P233 ~ P236

JobLauncher, SimpleJobLauncher

spring framework/spring-batch 2012.08.28 15:43 posted by dev.bistro

휴가중(진짜 심심해서 쓰는 ) 포스팅. 작성중


JobLauncher 의 유일한 구현체 SimpleJobLauncher이다.

1. 유일한 public method 'run'을 보면 Job , JobParameters 를 아귀먼트로 받는것을 확인할 수 이고,  return 은  JobExecution이다.

2. JobExecution은 Entity를 상속받는 상태를 나타내는 클래스라 생각해도 된다.



/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.batch.core.launch.support;

/**
 * Simple implementation of the {@link JobLauncher} interface. The Spring Core
 * {@link TaskExecutor} interface is used to launch a {@link Job}. This means
 * that the type of executor set is very important. If a
 * {@link SyncTaskExecutor} is used, then the job will be processed
 * within the same thread that called the launcher. Care should
 * be taken to ensure any users of this class understand fully whether or not
 * the implementation of TaskExecutor used will start tasks synchronously or
 * asynchronously. The default setting uses a synchronous task executor.
 * 
 * There is only one required dependency of this Launcher, a
 * {@link JobRepository}. The JobRepository is used to obtain a valid
 * JobExecution. The Repository must be used because the provided {@link Job}
 * could be a restart of an existing {@link JobInstance}, and only the
 * Repository can reliably recreate it.
 * 
 * @author Lucas Ward
 * @Author Dave Syer
 * 
 * @since 1.0
 * 
 * @see JobRepository
 * @see TaskExecutor
 */

public class SimpleJobLauncher implements JobLauncher, InitializingBean {
	protected static final Log logger = LogFactory.getLog(SimpleJobLauncher.class);
	private JobRepository jobRepository;
	private TaskExecutor taskExecutor;

	/**
	 * Run the provided job with the given {@link JobParameters}. The
	 * {@link JobParameters} will be used to determine if this is an execution
	 * of an existing job instance, or if a new one should be created.
	 * 
	 * @param job the job to be run.
	 * @param jobParameters the {@link JobParameters} for this particular
	 * execution.
	 * @return JobExecutionAlreadyRunningException if the JobInstance already
	 * exists and has an execution already running.
	 * @throws JobRestartException if the execution would be a re-start, but a
	 * re-start is either not allowed or not needed.
	 * @throws JobInstanceAlreadyCompleteException if this instance has already
	 * completed successfully
	 * @throws JobParametersInvalidException
	 */

	public JobExecution run(final Job job, final JobParameters jobParameters)
			throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException,
			JobParametersInvalidException {

		Assert.notNull(job, "The Job must not be null.");
		Assert.notNull(jobParameters, "The JobParameters must not be null.");

		final JobExecution jobExecution;
		JobExecution lastExecution = jobRepository.getLastJobExecution(job.getName(), jobParameters);
		if (lastExecution != null) {
			if (!job.isRestartable()) {
				throw new JobRestartException("JobInstance already exists and is not restartable");
			}
		}

		// Check the validity of the parameters before doing creating anything
		// in the repository...
		job.getJobParametersValidator().validate(jobParameters);

		/*
		 * There is a very small probability that a non-restartable job can be
		 * restarted, but only if another process or thread manages to launch
		 * and fail a job execution for this instance between the last
		 * assertion and the next method returning successfully.
		 */

		jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);

		try {
			taskExecutor.execute(new Runnable() {

				public void run() {
					try {
						logger.info("Job: [" + job + "] launched with the following parameters: [" + jobParameters
								+ "]");
						job.execute(jobExecution);
						logger.info("Job: [" + job + "] completed with the following parameters: [" + jobParameters
								+ "] and the following status: [" + jobExecution.getStatus() + "]");
					}
					catch (Throwable t) {
						logger.info("Job: [" + job
								+ "] failed unexpectedly and fatally with the following parameters: [" + jobParameters
								+ "]", t);
						rethrow(t);
					}
				}

				private void rethrow(Throwable t) {
					if (t instanceof RuntimeException) {
						throw (RuntimeException) t;
					}
					else if (t instanceof Error) {
						throw (Error) t;
					}
					throw new IllegalStateException(t);
				}
			});
		}
		catch (TaskRejectedException e) {
			jobExecution.upgradeStatus(BatchStatus.FAILED);
			if (jobExecution.getExitStatus().equals(ExitStatus.UNKNOWN)) {
				jobExecution.setExitStatus(ExitStatus.FAILED.addExitDescription(e));
			}
			jobRepository.update(jobExecution);
		}

		return jobExecution;
	}

	public void setJobRepository(JobRepository jobRepository) {
		this.jobRepository = jobRepository;
	}

	public void setTaskExecutor(TaskExecutor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}

	public void afterPropertiesSet() throws Exception {
		Assert.state(jobRepository != null, "A JobRepository has not been set.");
		if (taskExecutor == null) {
			logger.info("No TaskExecutor has been set, defaulting to synchronous executor.");
			taskExecutor = new SyncTaskExecutor();
		}
	}

}

---
public class JobExecution extends Entity {
	private JobInstance jobInstance;
	private volatile Collection stepExecutions = new CopyOnWriteArraySet();
	private volatile BatchStatus status = BatchStatus.STARTING;
	private volatile Date startTime = null;
	private volatile Date createTime = new Date(System.currentTimeMillis());
	private volatile Date endTime = null;
	private volatile Date lastUpdated = null;
	private volatile ExitStatus exitStatus = ExitStatus.UNKNOWN;
	private volatile ExecutionContext executionContext = new ExecutionContext();
	private transient volatile List failureExceptions = new CopyOnWriteArrayList();

       하략 ... 대부분 생성자/Get/Set



참고#1: http://chanwook.tistory.com/797

요약 : 4년전 교육 받았을때도 느꼈지만... 박찬욱님 짱 :)

'spring framework > spring-batch' 카테고리의 다른 글

JAXP DOM4J, JDOM2의 성능 비교  (0) 2013.11.13
Spring Batch Admin  (0) 2013.01.11
JobLauncher, SimpleJobLauncher  (0) 2012.08.28
JobParametersIncrementer의 사용.  (0) 2012.08.25


Job Parameter를 자동으로 Increment 하기 위해서 사용.

(Job의 구현체를 구분하는 방법은 Job + Job Parameter이기 때문에, Parameter없이는 같은 job을 계속 실행하면 안된다)





@Component
public class SimpleJobParametersIncrementer implements JobParametersIncrementer {

	static final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-hhmmss");
	public JobParameters getNext(JobParameters parameters) {
		String id = format.format(new Date());
		return new JobParametersBuilder().addString("run.id", id).toJobParameters();
	}

}
	
        
	    
	

	
		


요약
1. JobParametersIncrementer 구현
2. JobExplorerFactoryBean bean 설정
3. job에 increment로 1번 설정
4. 실행은 xmlfile jobanme [-next] 를 추가

참고

http://numberformat.wordpress.com/2010/02/07/multiple-batch-runs-with-spring-batch/


참고2 [BATCH_JOB_PARAMS] 테이블

JOB_INSTANCE_ID TYPE_CD KEY_NAME STRING_VAL DATE_VAL LONG_VAL DOUBLE_VAL

3 STRING run.id 20120825-124631 1970-01-01 09:00:00 0 0

4 STRING run.id 20120825-125909 1970-01-01 09:00:00 0 0


참고3. 기본적으로 제공하는 crementer는

org.springframework.batch.core.launch.support.RunIdIncrementer 가 있고 key를 프로퍼티로 받는다. 

https://fisheye.springsource.org/browse/spring-batch/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RunIdIncrementer.java?r=488ba7a37b70c62a2ac40d6c945ea940408add80


'spring framework > spring-batch' 카테고리의 다른 글

JAXP DOM4J, JDOM2의 성능 비교  (0) 2013.11.13
Spring Batch Admin  (0) 2013.01.11
JobLauncher, SimpleJobLauncher  (0) 2012.08.28
JobParametersIncrementer의 사용.  (0) 2012.08.25