BLOG main image
Candle
분류 전체보기 (30)
일상적인 story (0)
java script story (9)
java story (1)
web & was story (7)
db story (5)
flex story (0)
sever script story (2)
tool story (1)
etc story (3)
framework story (2)
20,262 Visitors up to today!
Today 0 hit, Yesterday 21 hit
daisy rss
tistory 티스토리 가입하기!
2008/07/24 13:12
클러스터드 논클러스터드 인덱스 낙서장

2008/03/20 13:18

복사 http://blog.naver.com/shinepm/60049236490

첨부파일 (1)

 클러스터드 인덱스와 넌 클러스터드 인덱스


인덱스는 클러스터드 인덱스와 넌 클러스터드 인덱스 두가지로 나눌 수 있다. 두 인덱스 간의 차이는 클러스터드 인덱스는 테이블 당 오직 하나만 생성할 수 있고, 넌 클러스터드 인덱스는 여러 개를 생성할 수 있다는 것이다.
 
인덱스는 모든 데이터를 B-Tree 형식으로 정렬해 놓게 된다. 클러스터드 인덱스는 키로 설정된 컬럼을 B-Tree 형식으로 정렬해 놓는데, 리프 레벨에서 아예 데이터 페이지 자체를 정렬해 놓는다. 이에 반해서 넌 클러스터드 인덱스는 별도의 인덱스 페이지를 생성하여 이를 관리한다. 그러므로 데이터 페이지 자체를 정렬해놓는 클러스터드 인덱스는 더 이상 추가가 불가능한 것이다.
 
인덱스 페이지의 구조는 이렇게 해당 테이블에 클러스터드 인덱스가 있느냐 아니면 넌 클러스터드 인덱스이냐에 따라 다른 구조를 띄게 된다. 좀더 정확히는 클러스터드 인덱스가 없는 넌 클러스터드 인덱스냐, 클러스터드가 있는 넌 클러스터드 인덱스이냐에 상관하는 형태를 가진다는 것이다.


클러스터드 인덱스

 

앞의 내용에서 사용한 힙 테이블을 기준으로 클러스터드 인덱스만을 가지는 테이블을 만들어 보자. 방법은 넌 클러스터드의 경우와 유사하며, 다만 리프 레벨 페이지가 직접 데이터 페이지가 된다는 점만이 다르다.


그림을 보면 실제 데이터 페이지 자체를 정렬해서 이것이 리프 레벨노드로 사용되고, 그 위에 넌 리프 레벨 노드와 루트 노드가 생성되었음을 알 수 있다. 데이터 페이지가 많지 않아 중간 레벨 노드들은 없었다. 기존 RID 대신에 최종 레벨 노드들은 인덱스 페이지의 첫 번재 로우값을 가지게 된다. 포인터 점프 대신에 데이터 페이지의 첫 첫번째 컬럼 값을 가지고 해당 데이터 페이지로 이동하여 데이터 페이지의 첫 번째 값부터 순차적으로 읽어 들이게 된다.
 
클러스커드 인덱스에서 값을 조회해보자. 검색할 데이터는 번호가 4번인 데이터이다. 역시 데이터 검색은 루트 노드부터 시작하게 된다. 루트노드에서 값이 4번인 것은 데이터 페이지 1에 있다는 것을 알 수 있다. 중간 레벨 노드들이 많았다면 아마도 몇 가지 레벨에 거쳐서 이러한 탐색 단계들을 진행해야만 할 것이다.


 

 클러스터드 인덱스가 없는 넌 클러스터드 인덱스 구조

아래<그림>은 클러스터드 인덱스가 없는 넌 클러스터드를 나타낸다. 첫 번째 레벨과 두 번째 레벨까지의 노드들은 인덱스 페이지들이며, 가장 하위의 것은 트리의 리프 레벨 노드들이 아니라 무작위로 저장되어 있는 데이터 페이지들이다. 그림에서는 intermediate레벨 노드들은 존재하지 않고 루트 노드와 리프노드로 직접 구성되어 있다. 리프 노드들은 데이터 페이지로의 포인터(이를 Row ID 혹은 RID(Relative Identifier)라고 부르기도 한다.)를 링크하고 있다.


이렇게 실제 데이터를 가져오기 위해서 리프 노드에서 데이터 페이지로 이동하는 것을 포인터 점프(Pointer Jump)라고 부른다. 클러스터드 인덱스에서는 리프 레벨이 데이터 페이지이므로 이러한 포인터 점프가 필요 없다. 포인터 점프는 쿼리의 퍼포먼스에 영향을 미칠 수도 있다.
 

좀더 실제적인 예를 가지고 살펴보자 우선 클러스터드든 넌 클러스터드든 아무런 인덱스도 설정되지 않은<그림1>와 같은 테이블이 있다. 이렇게 아무런 인덱스도 설정되지 않은 테이블을 힙 테이블(Heap Table)라고 한다. 데이터는 정렬되어 있지 않고 무작위로 들어 있다. 컬럼은 번호, 이름, 주소, 나이 순으로 되어 있고, 모두 11개의 로우들로 구성되어 있는 간단한 주소 테이블이다.
 

                                                            <그림1>

이 테이블의 데이터 페이지 구성은 <그림2>과 같으며, 무작위 순으로 되어 있다. (예제를 간단히 표현하기 위해서 하나의 데이터 페이지에는 모두 4개의 로우들만 들어 갈 수 있다고 가정 하였다)

                                                             <그림2>
 
모두 3개의 데이터 페이지로 구성되어 있으며 페이지 1과2는 모두 채워져 있고 페이지 3은 여분으로 로우 하나가 더 추가 될 수 있다.(실제 상황이라면 이렇게 로우 개수를 기준으로 데이터 페이지가 채워지는 것은 아니다. 당연히 로우가 가진 실제 데이터에 맞추어서 저장 되어진다.)
 
데이터 페이지에 저장된 것은 컬럼의 정열 순서와는 아무런 상관도 없다. 순전히 데이터가 추가된 순서라고 할 수 있다. 예를 들어 번호가 1인 김수영 로우가 가장 먼저 Insert 되고, 다음에 5번인 김시원 데이터가 저장되었다.
 
이를 번호 순으로 정렬하면 <그림3>과 같은 리스트가 만들어진다. 옆에 있는 Row ID는 앞에 강좌에서 설명한 것처럼 데이터 파일, 데이터페이지 번호, 로우 번호로 구성되는 것으로써 그림에서 번호 2의 경우 ‘1-1-1’ 1번 데이터 파일에 1번 페이지의 1번 로우라는 데이터 페이지 포인터 값을 가상으로 표현한 것이다. 일단 정렬된 리스트가 있으면 이를 인덱스 페이지로 구성하는 것은 매우 간단하다.

 

넌 클러스터드 인덱스를 만드는 것은 어려운 일이 아니다. 인덱스 컬럼으로 선택된 컬럼들을 기준으로 데이터 페이지를 정렬해서 이를 B-Tree로 구성하고, 리프 레벨에서는 실제 데이터페이지로 링킹 될 수 있도록 RID를 매팅한다.


클러스터드 인덱스가 없는 넌 클러스터드 인덱스 상황에서 원하는 값을 찾을 때 어떻게 수행되는지를 알아보자. 인덱스의 구축은 최하위 레벨인 리프 레벨에서부터 루트 노드로 상향식으로 이루어졌지만, 탐색은 정반대로 루트 노드에서 리프 레벨 노드로 이루어진다. 우선 번호 15를 가지고 루트 노드의 로우들과 비교한다.

여기서 로우 아이디를 기준으로 포인터 점프(Pointer Jump)를 한다. 포인터 점프는 데이터 페이지로 링크하는 것이다. 

Trackback Address :: http://follet.tistory.com/trackback/30
Name
Password
Homepage
Secret
2008/06/18 12:23

Log4j 사용법

 

Log4j 상세 설명 및 예제 프로그램

 

 

 

 

 

 

 

작성자:          홍혜성 hicomet@nate.com

작성일:          200613

 

Log4j 사용 예제 프로그램(1)

[1] Log4jTest.java

 

import org.apache.log4j.Logger;

              

public class Log4jTest

{

        protected static final Logger logger = Logger.getLogger(Log4jTest.class);

              

        public static void main(String[] args)

        {

               if (logger.isDebugEnabled()) {

                       logger.debug("프로그램 DEBUG");

               }

               if (logger.isInfoEnabled()) {

                       logger.info("프로그램 INFO");

               }

                logger.warn("프로그램 WARN");

               logger.error("프로그램 ERROR");

               logger.fatal("프로그램 FATAL");

        }

}      

 

[2] log4j.properties

 

## info 이상만 출력 허용 (debug Priority은 출력되지 않음)

## ROOT appender R 로 지정함

log4j.rootCategory=info, R

              

## 콘솔에 출력

log4j.appender.R=org.apache.log4j.ConsoleAppender

              

## 패턴 : 날짜출력 Priority출력 클래스명출력 - 메시지출력 개행

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{2} %x - %m%n

 

[3] 결과

 

D:\study\log4j>javac Log4jTest.java

D:\study\log4j>java Log4jTest

2006-01-02 16:19:18,671 INFO  Log4jTest  - 프로그램 INFO

2006-01-02 16:19:18,671 WARN  Log4jTest  - 프로그램 WARN

2006-01-02 16:19:18,671 ERROR Log4jTest  - 프로그램 ERROR

2006-01-02 16:19:18,671 FATAL Log4jTest  - 프로그램 FATAL

 

Log4j 사용 예제 프로그램 (2)

 [1] Log4jTest.java

 

import org.apache.log4j.Logger;

import org.apache.log4j.PropertyConfigurator;

              

public class Log4jTest

{

        public static void main(String[] args)

        {

               // ROOT

               Logger rootLogger = Logger.getRootLogger();

               rootLogger.info("프로그램 시작");

              

               // Logger1

               Logger logger1 = Logger.getLogger("com.search1");

               if (logger1.isDebugEnabled()) {

                       logger1.debug("프로그램 DEBUG");

               }

               if (logger1.isInfoEnabled()) {

                       logger1.info("프로그램 INFO");

               }

               logger1.warn("프로그램 WARN");

               logger1.error("프로그램 ERROR");

               logger1.fatal("프로그램 FATAL");

                             

               // Logger2

               Logger Logger2 = Logger.getLogger("com.search2");

               if (Logger2.isDebugEnabled()) {

                       Logger2.debug("프로그램 DEBUG");

               }

               if (Logger2.isInfoEnabled()) {

                       Logger2.info("프로그램 INFO");

               }

               Logger2.warn("프로그램 WARN");

               Logger2.error("프로그램 ERROR");

               Logger2.fatal("프로그램 FATAL");

              

               // ROOT

               rootLogger.info("프로그램 끝");      

        }

}

 

[2] log4j.properties

 

## info 이상만 출력 허용 (debug Priority은 출력되지 않음)

## ROOT appender R 로 지정함

log4j.rootCategory=info, R

 

## com.search1 패키지의 로깅에는 warn 이상만 출력

## additivity = false 로 지정했으므로 log4j.search1.log 에만 출력됨

## additivity = true 로 지정하면 log4j.log, log4j.search1.log 모두에 출력됨

log4j.category.com.search1=warn, search1

log4j.additivity.com.search1=false

 

## com.search2 패키지의 로깅에는 info 이상만 출력

log4j.category.com.search2=info, search2

log4j.additivity.com.search2=false

 

## DailyRollingFileAppender 는 파일 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있는 Appender

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

 

## priority 설정, 만약 Threshold=fatal 을 설정하면

## log4j.category.com.search1=warn, search1 를 설정했더라고 fatal 이상만 출력 된다.

log4j.appender.R.Threshold=debug

 

## ImmediateFlush 기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미

log4j.appender.R.ImmediateFlush=true

 

## log4j.log 파일에 출력 (디렉토리는 미리생성해 놓아야 에러 나지 않음)

log4j.appender.R.File=/study/log4j/log/log4j.log

 

## 기본값은 true이며 파일 끝에 추가하는 것을 의미한다.

## false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.

log4j.appender.R.Append=true

 

## 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있다.

## 형식은 SimpleDateFormat 을 따른다. (":" 문자는 사용 금지)

log4j.appender.R.DatePattern='.'yyyyMMdd

 

## 패턴 : 날짜출력 Priority출력 클래스명출력 - 메시지출력 개행

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{2} %x - %m%n

 

log4j.appender.search1=org.apache.log4j.DailyRollingFileAppender

log4j.appender.search1.Threshold=debug

log4j.appender.search1.ImmediateFlush=true

log4j.appender.search1.File=/study/log4j/log/log4j.search1.log

log4j.appender.search1.Append=true

log4j.appender.search1.DatePattern='.'yyyyMMdd

log4j.appender.search1.layout=org.apache.log4j.PatternLayout

log4j.appender.search1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

              

log4j.appender.search2=org.apache.log4j.DailyRollingFileAppender

log4j.appender.search2.Threshold=debug

log4j.appender.search2.ImmediateFlush=true

log4j.appender.search2.File=/study/log4j/log/log4j.search2.log

log4j.appender.search2.Append=true

log4j.appender.search2.DatePattern='.'yyyyMMdd

log4j.appender.search2.layout=org.apache.log4j.PatternLayout

log4j.appender.search2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

 

[3] 결과

 

(1) log4j.log

        2006-01-02 16:29:35,984 INFO  root  - 프로그램 시작

        2006-01-02 16:29:35,984 INFO  root  - 프로그램 끝

 

(2) log4j.search1.log

        2006-01-02 16:29:35,984 프로그램 WARN

        2006-01-02 16:29:35,984 프로그램 ERROR

        2006-01-02 16:29:35,984 프로그램 FATAL

 

(3) log4j.search2.log

        2006-01-02 16:29:35,984 프로그램 INFO

        2006-01-02 16:29:35,984 프로그램 WARN

        2006-01-02 16:29:35,984 프로그램 ERROR

        2006-01-02 16:29:35,984 프로그램 FATAL

Log4j 상세 설명

org.apache.log4j.Logger 사용

 

n         Category extends 받은 Logger 클래스 사용

ü        org.apache.log4j.Logger extends org.apache.log4j.Category)

ü        Category.getInstance() 방식은 deprecated .
대신 Logger.getLogger() 방식으로 대체됨

 

      public static Logger getLogger(String name);

      public static Logger getLogger(Class clazz);

      public static Logger getRootLogger();

      public static Logger getLogger(String name, LoggerFactory factory);

 

주요 컴포넌트

 

n         Categories

n         appenders

ü        콘솔, 텍스트파일, html 파일, xml 파일, 소켓, Windows NT Event Log, 이메일 전송 가능

ü        ConsoleAppender, FileAppender, SMTPAppender, SocketAppender, NTEventLogAppender, SyslogAppender, JMSAppender, AsyncAppender, NullAppender

n         layouts : 메시지 형식

 

Priority(우선권)

 

      debug : 디버깅 메세지

      info : verbose 모드에서 출력될만한 메세지

      warn : 이상없이 계속 실행될 수 있는 정도의 경고메세지

      error : 그럭저럭 돌아갈만한 정도의 에러메세지

      fatal : 비정상적으로 종료될 치명적인 메시지

 

Appender 옵션

 

전체 옵션

log4j.configuration=app_config.properties

log4j.debug=true

log4j.disable=INFO

log4j.additivity.your.category.name=false

log4j.defaultInitOverride=false

log4j.disableOverride=false

ConsoleAppender

Threadhold=WARN

ImmediateFlush=true

Target=System.err

FileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

RollingFileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

MaxFileSize=100KB

MaxBackupIndex=2

DailyRollingFileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

DatePattern='.'yyyy-ww

 

n         log4j.configuration=app_config.properties

ü        ex> java –Dlog4j.configuration= app_config.properties … 형식으로 속성 파일 설정

n         log4j.debug=true

ü        기본값은 false. log4j 를 설정하는 상세 정보를 출력

n         Log4j.disable=INFO

ü        모든 category에서 여기 지정한 priority 보다 같거나 낮은 priority 메세지는 로깅하지 않는다. (log4j.disableOverride=false 일때에만 동작)

n         log4j.additivity.your.category.name=false

ü