2012년 11월 27일 화요일

20121127 점심시간 운동

오랫만에 점심시간에 운동을 했다.

저녁시간에 운동하는 계획을 세웠었는데 지키기가 참 어렵다.

점심시간, 저녁시간 따지지 말고 시간이 나면 운동하자.


스트레칭
  • 팔 스트레칭
  • 다리
  • 반달 자세
  • 다리 자세
  • 물고기 자세
  • 코브라 자세
  • 고양이 자세
  • 낙타 자세
맨손운동
  • 복근운동 상체들기 10회 2 set
  • 복근운동 다리들기 10회 2 set
  • 팔굽혀펴기 5회
한동안 운동을 안했고, 오늘도 갑작스럽게 운동을 결정한거라 귀찮음을 극복하지 못하고 복근운동과 맨손 근력 운동을 부실하게 했다. 

차근차근 횟수를 늘려가자.

트레드밀
  • 6 - 5분
  • 8 - 10분
  • 5 - 3분
달리기는 그럭저럭 예전 만큼 할만했다.

지금 상태를 몇일 더 유지하자.

트레드밀 후 다리 스트레칭

  • 벽 밀기
근력운동이나 다른 운동은 시간 부족으로 못했다.

점심시간에 운동을 하면 앞으로도 이런 패턴일 것 같다.

짧은 시간이라도 열심히 운동하자.


2012년 11월 26일 월요일

실행계획 데이터베이스 튜닝 - 실행계획분석 18

193P

소트 머지 조인

소트 머지 조인의 모든 장점을 제공하면서 소트 머지 조인의 단점까지 어느 정도 보완한 해쉬 조인 사용

소트 머지 조인은 중첩 루프 조인이나 해쉬 조인과 달리 어느 테이블이 먼저 엑세스되고 어느 테이블이 나중에 엑세스되는가는 큰 영향이 없다.

소트 머지 조인은 각 테이블에서 조건에 만족하는 데이터를 추출한 후 조인 조건으로 각 집합을 정렬한다.

정렬된 두 개의 집합에 대해 머지 조인을 수행하고 조인에 실패한 데이터는 버려진다.

정렬에 많은 비용이 발생.

머지 조인 알고리즘이 해쉬 함수에 비해 성능이 보장되지 않음.

대용량일 경우 해쉬 조인, 적은 데이터일 경우 중첩 루프 조인

소트 머지 조인은 조인 SQL의 조인 조건에 인덱스를 이용하지 못할 경우 자주 발생한다.

조인 조건에 인덱스가 없으면 오라클 옵티마이져는 중첩 루프 조인을 선택하지 않는 경우가 많다.


196P

카테시안 조인이 소트 머지 조인과 동일하지는 않으나 실행 계획이 소트 머지 조인 실행 계획의 형식으로 생성된다.

FROM 절의 테이블을 연결할 때 WHERE 절에서 테이블을 연결하는 조인 조건이 없을 경우 카테시안 조인이 발생한다.


199P


CentOS 설치

CentOS-6.3-x86_64-LiveDVD.iso 로 설치

기본과정은 생략

1. 파티션 분할

기본으로 하고 /root의 크기를 줄이고 /home 크기를 늘렸다.


# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vg_livedvd-lv_root
                       20G  4.5G   15G  24% /
tmpfs                1004M  260K 1004M   1% /dev/shm
/dev/sda1             485M   38M  422M   9% /boot
/dev/mapper/vg_livedvd-lv_home
                       56G  180M   53G   1% /home


2. 네트워크 설정


DEVICE=eth0
BOOTPROTO="none"
IPADDR="xxx.xxx.xxx.xxx"
NETMASK="xxx.xxx.xxx.xxx"
GATEWAY="xxx.xxx.xxx.xxx"
DNS1="168.126.63.1"
DNS2="xxx.xxx.xxx.xxx"
TYPE="Ethernet"
IPV6INIT="no"

IPV6INIT="no" 이 라인을 빼면 에러 메시지가 한 줄 출력된다.


3. 계정생성

useradd -d 홈디렉토리 -s shell 계정명

4. telnet 확인

rpm -qa | grep telnet

아무것도 없는 것을 확인.

5. ssh 설정

기본적으로 설치된다.

vi /etc/ssh/sshd_config

LoginGraceTime 1m
PermitRootLogin no

두 라인 주석 제거 후 service sshd restart

6. 전체 계정 잠금 설정

vi /etc/pam.d/system-auth

auth        required      pam_tally2.so onerr=fail      deny=3  no_magic_root reset
account     required      pam_tally2.so onerr=fail      no_magic_root

두 라인 추가. 서비스를 재시작하지 않아도 바로 적용된다.

7. 잠금 설정을 테스트 하기위해 계정 추가

                                                                                                                                 





2012년 11월 24일 토요일

RedHat vs. CentOS

이번에 가상화를 진행하면서 Solaris를 사용하던 서버들을 Linux로 옮길 계획을 가지고 있었다.

그동안 RedHat이 Windows와 마찬가지로 라이선스 키가 없으면 설치도 안되는 줄 알고 있었는데 확인해보니 설치는 가능하나 라이선스 키가 없으면 패키지를 업데이트 하거나 보안 패치 등을 받을 수 없었다. 물론 기술지원도 받을 수 없다.

곰곰히 생각해보니 yum을 이용한 패키지 설치나 업데이트가 되지 않는다면 너무 번거로울 것 같아 대안으로 CentOS를 고민하게 되었다.

CentOS는 RHEL의 클론으로 무료로 yum을 이용한 패키지 설치나 업데이트가 가능하다.

테스트 서버가 아닌 실제 서버에 오픈소스를 올리는 것이 부담스럽기도 하지만 생각해보면 이미 많은 부분을 오픈소스로 사용하고 있으니 그 부분을 일단 덮어두기로 했다.

2012년 11월 5일 월요일

실행계획 데이터베이스 튜닝 - 실행계획분석 17

174P

해쉬 조인

대용량 데이터의 연결을 해결하기 위한 조인 방법

BUILD 테이블 - PROBE 테이블

180P

해쉬 조인의 성능은

BUILD 테이블의 빠른 해쉬 영역 생성
PROBE 테이블에 대한 최적의 엑세스
BUILD 테이블에 대한 최적의 엑세스

해쉬영역의 크기는 BUILD 테이블에 의해 추출되는 데이터의 건수에 의해 좌우된다.

해쉬 영역의 크기가 크다면 모든 데이터가 메모리에 구성되지 못하고 임시 테이블스페이스를 사용한다.

임시 테이블스페이스는 디스크에 존재한다.

해쉬 영역의 크기가 크다면 디스크에 있는 임시 테이블스페이스에 많이 엑세스해야하고 이는 디스크 I/O의 증가를 의미한다.

결국 BUILD 테이블에서 데이터를 적게 추출하여 해쉬 영역의 크기를 감소시키는 것이 해쉬 조인의 성능을 향상시키는 가장 중요한 항목이다.

PROBE 테이블은 중첩 루프 조인과 달리 조인 조건을 상수로 제공받지 못한다.

이 점이 중첩 루프 조인과 해쉬 조인의 가장 큰 차이점이다.

PROBE 테이블에서 추출되는 데이터가 적으면 인덱스, 많으면 전체 스캔.

전체 스캔인 경우 병렬 프로세싱.

/*+ ORDERED USE_HASH(A, B) PARALLEL(B, 4) */

184P

192P

실행계획 데이터베이스 튜닝 - 실행계획분석 16

150P

DRIVING 테이블 선정 조건

조인 조건을 제외한 WHERE 조건이 없을 경우
1:M 관계의 모델링에서 1에 해당하는 테이블을 DRIVING 테이블로 선정
1:1 관계에서는 어느 테이블이든 DRIVING 테이블이 될 수 있다.
M:N 관계에서는 COUNT 함수를 수행하여 가장 작은 값을 추출하는 테이블을 DRIVING 테이블로 선정해야 한다.

조인 조건을 제외한 WHERE 조건이 있을 경우
각 테이블의 WHERE 조건으로 COUNT 함수를 수행하여 가장 작은 값을 추출하는 테이블을 DRIVING 테이블로 선전해야 한다.

INDEX FAST FULL SCAN /*+ INDEX_FFS(테이블 이름, 인덱스 이름) */ 힌트와 인덱스를 활용

WHERE 조건에 조인 조건만 있고 대용량의 데이터에 엑세스해야 한다면 중첩 루프 조인보다 해쉬 조인을 이용하는 것이 유리

155P

160P

166p

중첩 루프 조인에서는 조인이 수행될 때마다 데이터가 감소하는 경우보다는 데이터가 증가하는 경우에 성능을 보장받을 수 있다.

168P

171P


2012년 11월 2일 금요일

실행계획 데이터베이스 튜닝 - 실행계획분석 15

130P

134P

중첩 루프 조인(NESTED LOOP)

DRIVING 테이블 - 먼저 엑세스 하는 테이블

INNER 테이블 - 뒤에 엑세스 하는 테이블

중첩 루프 조인에서 조인에 참여하는 테이블이 어떤 역할 을 수행하는가에 따라 SQL 최적화를 위한 인덱스가 변한다.

DRIVING 테이블
조건을 만족하는 데이터에 대해 한 번만 엑세스하며 조인 조건을 상수로 제공받지 못한다.

INNER 테이블
DRIVING 테이블에서 추출되는 데이터 건수만큼 반복 수행하며 조인 조건을 상수로 받는다.

----

DRIVING 테이블
실행 계획에서 위에 생성되는 테이블이 DRIVING 테이블의 역할을 수행하며 커리 밤위를 감소시키는 역할로 조인 조건을 사용할 수 없게 된다.
DRIVING 테이블은 조건을 만족하는 데이터에 한 번만 엑세스한다.

INNER 테이블
실행 계획에서 밑에 생성되는 테이블
조인 조건을 처리 범위 감소 조건으로 사용할 수 있다.
DRIVING 테이블에서 추출되는 데이터의 건수만큼 반복 수행하며 조인 조건을 상수로 제공받는다.

----

140P

향상된 중첩 루프 조인

DRIVING 테이블과 INNER 테이블이 1:M의 관계일 때 하나 하나에 대해 랜덤 엑세스를 수행하는 것이 아니라 DRIVING 테이블에서 추출한 값에 대해 INNER 테이블의 인덱스에서 추출되는 여러 건에 대한 한 번에 값을 모아 INNER 테이블에 엑세스한다.

INNER 테이블의 데이터가 정렬되어 저장되어 있다면 몇 개의 블록만 엑세스하여 모든 결과를 추출할 수 있다.

향상된 중첩 루프 조인을 사용하면 INNER 테이블에 엑세스하는 I/O의 횟수를 감소시킬 수 있다.

향상된 중첩 루프 조인이 효과적으로 사용되기 위해서는 클러스터링 팩터가 양호해야 한다.

특정 컬럼으로 데이터가 모여서 저장되어 있는지 아닌지를 클러스터링 팩터라고 한다.

향상된 중첩 루프 조인을 효과적으로 이용하려면 다음의 조건을 만족해야 한다.

1:M 관계의 테이블들에 대한 중첩 루프 조인
1에 해당하는 테이블이 DRIVING 테이블로 수행되며 M에 해당하는 테이블이 INNER 테이블로 수행
M에 해당하는 테이블은 조인 조건에 의해 정렬되어 데이터 저장(조인 컬럼에 의해 M에 해당하는 테이블은 클러스터링 팩터 양호)

----

144P

중첩 루프 조인에서 성능을 좌우하는 항목

INNER 테이블의 효과적인 엑세스
DRIVING 테이블에서 추출되는 데이터 건수
DRIVING 테이블의 엑세스 최적화

----

INNER 테이블의 반복 엑세스를 어떻게 최적화할 것인가? - 최적화된 인덱스

EX) KR-CODE + 거래일자

중첩 루프 조인의 성능 최적화에서 가장 중요한 요소는 INNER 테이블의 반복 엑세스를 최적화 하는 것이다.

INNER 테이블의 반복 엑세스를 최적화하기 위해서는 처리 범위를 최대한 감소시킬 수 있는 인덱스가 선정되어야 한다.

중첩 루프 조인에서 INNER 테이블은 조인 조건을 상수로 제공받고, 일반적으로 조인 조건에서 점 조건을 사용하기 때문에 INNER 테이블의 인덱스 선정은 성능의 핵심이 될 것디다.

INNER 테이블에서 조인 조건과 그외 점 조건으로 인덱스를 구성하고 선분 조건을 인덱스 뒤에 추가하는 것이 가장 효과적이다.

----

DRIVING 테이블의 처리 범위

----


149P

실행계획 데이터베이스 튜닝 - 실행계획분석 14

123p

대용량 테이블에서 3~5% 이상의 데이터를 추출하는 경우 인덱스를 이용하면 처리 범위 및 랜덤 엑세스의 증가로 인해서 엄청난 성능 저하가 발생한다.

이런 경우엔는 테이블 전체 스캔을 고려한다.

테이블 전체 스캔

첫번째 방법은 힌트 /*+ FULL(테이블 이름) +/

두번째 방법은 인덱스 컬럼에 데이터를 변경시키지 않는 함수를 사용

인덱스 컬럼이 함수에 의해 가공되면 해당 인덱스를 이용할 수 없다.

대용량 테이블에서 많은 양의 데이터를 추출할 경우에 테이블을 전체 스캔하는 이유는 랜덤 엑세스 때문이다.

테이블 전체 스캔은 랜덤 엑세스를 제거할 수 있으므로 많은 데이터에 엑세스하는 SQL의 경우에 인덱스를 이용하는 것보다 더 좋은 성능을 보장받을 수 있다.

또한, 테이블 전체 스캔은 다중 블록 I/O를 수행하기 때문에 대용량의 데이터를 추출하는 SQL에 대해서는 인덱스 스캔보다 성능적으로 유리할 수 있다.

126P

기본적으로 오라클에서는 하나의 SQL에는 하나의 프로세스가 기동되어 필요한 데이터에 엑세스한다.

병렬 프로세싱을 이용하면 설정한 개수만큼의 프로세스가 기동하여 작업을 나누어 수행한다.

운영 체제에서 여러 개의 프로세스를 기동하기 위해서는 운영 체제의 자원을 사용해야 한다. 그렇기 때문에 여러 개의 프로세스를 기동시키기 위한 시간이 소요된다. 프로세스를 많이 기동시킬수록 운영 체제의 병렬 프로세스 기동 시간은 증가한다. 따라서, 크기가 작은 테이블에 병렬 프로세싱을 적용하면 테이블에 엑세스하는 시간보다 프로세스를 기동시키는 시간이 더 많이 소요될 수 있기 때문에 성능이 저하될 수 있다.

1GB 이상의 테이블에서 병렬 프로세싱을 이용하는 것이 효과적.

병렬 프로세싱을 사용하기 위한 데이터베이스 파라메터 설정 확인이 필요.

PARALLEL_MIN_SERVER - 시스템에서 사용할 수 있는 최소 병렬 프로세싱 개수

PARALLEL_MAX_SERVER - 최대 병렬 프로세싱 개수

PARALLEL_AUTOMATIC_TUNING - 병렬 프로세싱의 메시지 저장 공간과 병렬 프로세스 사이의 통신을 위한 I/O 단위를 설정

PARALLEL_AUTOMATIC_MESSAGE_SIZE - 병렬 프로세스 사이의 통신을 위한 I/O 크기

----

PARALLEL_AUTOMATIC_TUNING = TRUE/FALSE

TRUE - 병렬 프로세스 사이에 통신을 수행하기 위해 사용하는 메시지는 오라클 메모리 공간 중에서 LARGE POOL 공간을 사용한다.

FALSE - SHARED POOL 공간을 사용

SQL에 대한 파싱 정보를 저장하는 SHARED POOL 영역을 사용한다면 메모리 사용에 비효울이 발생한다.

TRUE로 설정하면 병렬 프로세스 사이에서 통신을 하기 위한 I/O의 크기가 1KB에서 2KB로 변경된다.

128P

2012년 10월 30일 화요일

현대카드 ZERO 신청

현대카드 ZERO를 신청했다.

돈관리에 있어 와이프와 합의한 기본내용은 신용카드를 모두 없에고 체크카드 만을 쓰자. 였다.

모든 일이 그렇듯 이것도 계획한 대로 잘 되지는 않았다.

일단 둘 모두 체크카드에 매달 넣어두는 금액이 적었다.

가끔 월말에 결산을 하면서 넣어두는 돈을 조정하기는 했지만 그래도 부족한 경우가 많았다.

그때마다 신용카드를 쓰다보니 해지되지 않고 남아있는 신용카드가 몇 장 있어 이번에 결산을 하면서 큰맘먹고 모두 해지 신청을 했다.

그러다보니 해외구매를 할 때 사용하던 신용카드는 해지대상이었고 평소에 종종 사용하던 현대M카드는 국내 전용이어서 새로운 카드를 신청할 필요가 생겼다.

현대카드 홈페이지에 들어가 신용카드를 주욱 둘러보니, 일단 대부분의 신용카드가 연회비가 매우 비쌌다.

내가 꼼꼼하지 못해 신용카드 혜택을 잘 못챙기기 때문에 일단 연회비가 비싼 카드는 모두 제외하다보니 결국 남는건 ZERO 카드였다.

ZERO 카드의 장점은 일단 전월실적조건 ZERO.

대부분의 카드가 전월실적이 30~40만원이 되야 혜택이 유지되는 조건이라 전월실적조건이 없는 부분이 마음에 들었다.

물론 연회비가 낮고(해외구매 가능할 경우 만원), 전월실적조건이 없기에 혜택도 다른 카드에 비해 낮은 듯 하다.

하지만 위에서 얘기했듯이 난 신용카드 혜택을 꼼꼼히 챙기지 못하는 사람이다.

그리고 신용카드 사용은 최대한 자제하려고 한다.

그러기에 ZERO 카드가 나에게는 딱 맞게 느껴졌다.

하나 더, 신용카드 사용금액을 선결제 할 경우 추가 할인이 있다고 하니 잘 활용해야겠다.

음... 교통카드 기능이 있는지는 잘 모르겠다.

나중에 전화로 확인해보자.

온라인으로 신청했는데 신청단계 마지막에 리볼빙 서비스를 신청하는 단계가 있었던 것 같기도 하고 아닌것 같기도 하고... 애매하게 처리가 되어 있었다.

현대카드는 홈페이지나 온라인도 깔끔하게 잘 관리하는 듯한데 리볼빙 신청이 애매하게 되어 있었던 부분은 고의적인 것 같다.

잊어버리지 않기 위해 ZERO 카드 혜택을 간단히 기록해 둔다.

횟수제한, 전월실적조건, 할인한도 ZERO

모든 가맹점 이용금액의 0.7% 할인 - 1000원을 쓰면 7원 할인이다-_-; 10만원을 쓰면 700월 할인. 이건 뭐-_-;

생활필수 영역 이용금액의 0.5% 추가할인

이용일 5일 이내 선결제 시 0.3% 추가할인

모든 가맹점에서 2~3개월 할부 결제 시 무이자

카드 이름처럼 심플한 혜택-_-;



일요일, 일주일을 정리하는 방법

일요일에 일주일을 정리하는 방법에 대해 글을 쓰려고 했는데 참신한 아이디어가 떠오르지 않았다.

몇일을 미루다가 결국 그냥 써보기로 했다.

생각나는 대로, 생각의 흐름을 적어봐야겠다.

매일 하루를 반성하는 시간이 필요하다고 생각한다.

한 10분이라도 오늘의 나는 하루에 충실했는가를 돌아봐야 한다.

또한, 오늘 해야 했던 일들을 왜 못했는가, 오늘 못한 일들을 언제 해야 하는가도 매일 점검해야 한다.

이렇게 하루의 정리가 필요하듯이 일주일의 정리도 필요하다.

물론 일주일 뿐만 아니라, 한달, 분기, 반기, 그리고 일년의 반성도 필요할 것이다.

이런 일련의 반성의 토대가 되는 것이 하루, 그리고 일주일의 반성이다.

자, 이제 생각해보자. 일주일의 반성에는 어떤 항목이 포함되어야 할까?

일주일의 느낌을 자유롭게 적는 것도 좋겠지만, 일정한 틀이 필요하다고 생각된다.

업무일지를 쓰듯, 특정한 포멧이 필요하다.

예전에 자신을 표현하는 지표를 정해놓고 매달 점수를 매겨 스스로를 평가하는 것도 보았지만 현재 나에게 적용하기는 어려울 듯 하다.

음...

생각나는 대로 적어보자면,

월요일 부터 일요일까지 매일에 점수를 매기자.

각 요일마다 해야 할 일(일감)들이 있을테니 일감을 계획할때 각 일마다 10점 만점의 점수를 부여하고 모든 일들의 개수로 평균을 내자.

모든 일감이 10점이면 평균도 10점일 것이다.

이런 방식으로 점수를 매기려면 일감을 계획할 때 구체적으로 기록해야 한다.

그리고 생각만이라도 이런 기준을 만족하면 10점, 이런 부분이 부족할 경우 9점, 이런식으로 차등을 둘 수 있어야 할 것 같다.

괜찮은 방법 같다.

일을 계획할때 to-do list에 일의 제목만을 적는 것이 아니라 한번 더 생각해서 세분화하여 적고 점수도 생각해보자.

그리고 하루에 할 일을 너무 많이 계획하지 말자.

계획한 그날 해야 할 일을 모두 처리하지 못하면 평균값에서 처리하지 못한 일감 하나 당 1점씩 차감하자.

계획을 했으니 산으로 가더라도 일단 실행으로 옮겨보자.

오늘 반성 후 내일 계획부터 시작이다.

ps. 고민만 하지 말고 일단 글을 쓰자.

덧. 감점요일

그날 할일을 못하면 평균에서 1점 감점
일기를 쓰지 않으면 평균에서 1점 감점
내일 계획을 세우지 않으면 평균에서 1점 감점
시간이 어긋나면 개별 점수에서 1점 감점



2012년 10월 29일 월요일

20121029 운동


계획한 대로 운동!

운동하러 가기 전에 약간 미적거리다가 항상 9시 반이 되야 출발하게된다.

오늘도 9시 반에 출발했고 결과적으로 시간이 매우 빠듯했다.

9시 정각에 출발할 수 있도록 하자!


스트레칭
  • 팔 스트레칭
  • 다리
  • 반달 자세
  • 다리 자세
  • 물고기 자세
  • 코브라 자세
  • 고양이 자세
  • 낙타 자세
맨손운동
  • 복근운동 상체들기 - 다리들기 각 10회 4 set
  • 브릿지 45초, 45초, 45초
  • 팔굽혀펴기 6회
복근운동 횟수가 조금 늘었다. 앞으로 한동안 4set을 유지하고 횟수를 점차 늘리자.

팔굽혀펴기는 브릿지 다음에 해서 그런지 겨우 여섯 번 했는데 너무 힘들다-_-;


트레드밀
  • 6 - 5분
  • 8 - 10분
  • 5 - 5분
달리기 강도는 이쁘게 올라가고 있는 것 같다. 시간을 더 늘리고 한동안 8 속도를 유지하자.

트레드밀 후 다리 스트레칭

  • 벽 밀기
  • 서서 몸통 굽히기

근력운동

  • 딥 작게 5회 2set
    • 계속 어색한 자세 ㅠㅠ
  • 벤치 프레스 - empty bar 10회 3set
딥은 정말 자세가 안나온다.

얼마나 근력이 약하면 내 팔로 내 몸을 이렇게 지탱하게 힘들까-_-;

대체 할만한 운동을 찾아봐야겠다.

벤치 프레스는 지난 번 운동과 동일. set를 늘리려고 했는데 시간이 너무 촉박했다.

다음 운동은 20121101


맨손운동
  • 복근운동 상체들기 - 다리들기 각 11회 4 set
  • 브릿지 45초, 45초, 45초
  • 팔굽혀펴기 8회
트레드밀
  • 6 - 5분
  • 8 - 15분
  • 5 - 5분


근력운동
  • 딥 작게 5회 2set
  • 벤치 프레스 - empty bar 10회 4set
20121101에는 딥 어시스트 머신을 이용해봐야겠다.


sap 사이트 보고 공부 좀 더하자.


ps. 운동카드 반납 완료.

실행계획 데이터베이스 튜닝 - 실행계획분석 13

103

결합 컬럼 인덱스를 구성하는 컬럼의 순서

1순위 - 점 조건으로 사용된 컬럼

2순위 - 랜덤 엑세스 감소

3순위 - 정렬 제거

4순위 - 단일 컬럼의 분포도

WHERE 조건에 사용할 수 있는 연산자는 점 조건과 선분 조건으로 나뉜다.

SQL에서 최적의 인덱스는 처리 범위를 최소로 감소시키는 인덱스.

분포도가 좋다는 의미는 각 데이터가 중복되지 않고 고르게 퍼져 있는 것.

컬럼의 분포도가 좋으려면 동일 연산자(=)와 같은 점 조건으로 조회해야 한다.

따라서 선분 조건보다 점 조건이 있는 컬럼이 앞에 있어야만 처리 범위를 감소시킬 수 있다.

점 조건+선분 조건으로 인덱스를 생성하면 엑세스한 데이터에 대해 버려지는 데이터는 없다.

선분 조건 + 점 조건으로 인덱스를 생성하면 인덱스에 엑세스한 후 버려지는 데이터가 생긴다.

점 조건 + 점 조건으로 인덱스를 생성한다면 두 조건에 의해 처리 범위는 동시에 감소한다.

처리 범위만을 본다면 점 조건들의 순서가 변경되어도 처리 범위는 변하지 않게 된다.

선분 조건 + 선분 조건 인덱스를 생성하면 앞에 있는 선분 조건에 의해서만 처리 범위가 감소한다.

-----------------

결론

점 조건 + 점 조건 : 두 개의 점 조건에 의해 처리 범위 감소

선분 조건 + 선분 조건 : 앞의 선분 조건에 의해 처리 범위 감소

점 조건 + 선분 조건 두 개의 조건에 의해 처리 범위 감소

선분 조건 + 점 조건 : 앞의 선분 조건에 의해 처리 범위 감소

WHERE 절에 많은 조건이 있다면 점 조건들을 앞에 위치시키고 선분 조건을 뒤에 위치시켜 인덱스를 생성해야 처리 범위를 최소화할 수 있다.

* 결합 컬럼 인덱스의 처리 범위 최소화 규칙

----

두 개의 선분 조건은 연산자에 의해 추출되는 데이터의 양을 비교하여 연산자에 의한 분포도가 더 좋은 걸럼이 앞에 있어야 처리 범위를 더 감소시킬 수 있다.

----

인덱스를 이용하여 랜덤 엑세스를 제거하기 위해서는 랜덤 엑세스가 왜 발생하는지, 어떤 종류의 랜덤 엑세스가 있는지 이해해야 한다.

랜덤 엑세스의 종류는 3가지

1. 확인 랜덤 엑세스 - WHERE 조건을 인덱스에서 확인할 수 없을 경우 테이블에 엑세스해서 확인하는 랜덤 엑세스

2. 추출 랜덤 엑세스 - SELECT 절의 컬럼 값을 추출하기 위해 테이블에 엑세스하는 랜덤 엑세스

3. 정렬 랜덤 엑세스 - 정렬을 수행하는 ORDER BY 및 GROUP BY를 수행하기 위해 테이블에 엑세스하는 랜덤 엑세스

확인, 추출, 정렬 랜덤 엑세스의 제거는 처리 범위의 감소 다음으로 SQL의 성능에 있어 매우 중요하다.

----

결합 인덱스를 생성할 경우 단일 컬럼의 분포도

컬럼의 분포도가 아무리 좋아도 연산자를 선분 조건으로 사용하야 한다면 분포도는 나빠진다.

분포도가 나쁜 컬럼이라도 점 조건을 사용하여 여러 컬럼을 결합한다면 분포도가 좋아질 수 있다.

점 조건들,  선분 조건들의 순서를 정하기 위한 우선 순위를 선정할 경우에 단일 컬럼의 분포도를 고려해야 한다.

선분 조건에서는 단일 컬럼 자체의 분포도가 아니라 단일 컬럼의 분포도와 연산자에 의해 추출되는 데이터의 양을 업무에 적용하여 비교.

점 조건에는 해당 컬럼의 분포도를 그대로 적용.

----

데이블에 엑세스하는 대부분의 SQL을 함께 고려하여 최적의 인덱스를 선정


실행계획 데이터베이스 튜닝 - 실행계획분석 12

97

한 테이블에 인덱스의 개수가 많다면?

단점

1. DML 성능 저하
2. 디스크 공간 낭비
3. 인덱스 관리의 어려움
4. 인덱스 본연의 역할에 문제 발생

데이터가 테이블에 저장되면 인덱스에도 해당 값을 저장해야 한다.

인덱스의 경우에 여유 공간이 있는 블록에 데이터의 인덱스 값을 저장하는 것이 아니다.

인덱스는 저장되는 데이터 값에 의해 정렬되므로 정렬된 순서에 의해 추가되는 데이터를 저장해야 한다.

데이터가 인덱스에 저장되는 순간 값의 저장 위치가 정해진다.

그러므로 데이터가 테이블에 저장될 때보다 인덱스에 저장될 때 더 큰 부하가 발생한다.

100

유연성이 없는 단일 컬럼 인덱스를 사용하기 보다는 유연성이 높은 결합 컬럼 인덱스를 이용한다면 테이블의 인덱스 개수를 줄일 수 있다.

조회 성능을 최적화하면서 인덱스 개수를 최소화.



2012년 10월 28일 일요일

20121028 어항일지 1

어항의 물을 반 가까이 갈았다.

수족관을 산 곳에서는 일주일에 한번 4분의 1정도의 물을 갈아주라고 했는데 한동안 물관리에 신경을 쓰지  않은듯해서 한번에 많이 갈았다.

그리고 수족관 벽에 짙은 녹조가 끼어 있어서 수위를 낮추고 벽을 닦아야만 했기에 더더욱 물을 많이 버릴 수 밖에 없었다.

물을 갈고 스펀지와 산소 발생기를 청소했다.

스펀지는 매일 청소하라고 했는데 일주일에 한번 밖에 안해주는 듯하다-_-;

음... 수초들의 상태는 그리 좋아 보이지 않는다.

물고기들의 상태는 양호한 것 처럼 보인다.

현재 주황색 줄무늬 열대어 3마리, 노란색 지느러미 물고기 4마리,  청소물고기라 불리는 녀석이 한마리, 그리고 새우 비슷하게 생긴 녀석 한마리 총 9마리가 살고 있다.

얘들아 앞으로 잘 지내보자!

2012년 10월 26일 금요일

20121026 운동

계획은 25일 운동이었는데 수요일에 술을 먹어서 수요일 정시퇴근을 목요일로 미루고 목요일 정시퇴근을 금요일로 미뤘다.

앞으로는 빼먹지 말자.


스트레칭
  • 팔 스트레칭
  • 다리
  • 반달 자세
  • 다리 자세
  • 물고기 자세
  • 코브라 자세
  • 고양이 자세
  • 낙타 자세
맨손운동
  • 복근운동 상체들기 - 다리들기 각 10회 3 set
  • 브릿지 45초, 45초, 45초
  • 팔굽혀펴기 4회
트레드밀
  • 6 - 5분
  • 7.5 - 15분
  • 5 - 4분
트레드밀 후 다리 스트레칭

  • 벽 밀기
  • 서서 몸통 굽히기

근력운동

  • 딥 작게 5회 2set
    • 계속 어색한 자세 ㅠㅠ
  • 벤치 프레스 - empty bar 10회 3set


다음 운동은 20121029

추가할 운동
?

sap 사이트 보고 공부 좀 더하자.


ps. 운동카드 반납 완료.

java - 상속과 다형성

하위 클래스가 상위 클래스로부터 상속 받는다.

자바에서는 하위 클래스가 상위 클래스를 확장(extend)한다고 얘기한다.

하위 클래스는 상위 클래스의 인스턴스 변수와 메소드를 자동으로 상속받는다.

하위 클래스에서 별도의 메소드와 인스턴스 변수를 추가할 수도 있고, 상위 클래스에서 상속받은 메소드를 오버라이드 할 수도 있다.


2012년 10월 25일 목요일

실행계획 데이터베이스 튜닝 - 실행계획분석 11

90

랜덤 엑세스는 말 그대로 무작위 데이터 추출을 의미한다.

테이블의 전체 데이터 중에서 어느 정도 엑세스해야 많은 데이터이며 어느 정도 엑세스해야 적은 데이터인지에 대한 기준을 제시하는 한 요소가 랜덤 엑세스

----

인덱스에는 키 컬럼의 값과 ROWID 값이 저장되어 있다.

ROWID는 테이블에 저장되어 있는 각 데이터에 할당된 주소와 같다.

그러므로 데이터 베이스에 있는 모든 데이터는 서로 다른 ROWID 값을 갖는다.

인덱스를 생성할 경우 인덱스 컬럼의 값과 함께 해당 데이터의 ROWID가 함께 저장된다.

따라서 인덱스에 엑세스하면 조건을 만족하는 값에 대해 ROWID를 제공받고 해당 ROWID 값으로 테이블에 엑세스한다.

인덱스를 이용한 테이블 엑세스는 인덱스에서 ROWID 값을 확인하고, 해당 ROWID 값을 이용하여 테이블에서 해당 데이터 만을 추출하는 것을 의미한다.

ROWID 값으로 테이블에 엑세스하는 방식을 랜덤 엑세스라고 한다.

----

SQL 수행 시 랜덤 엑세스가 증가하면 SQL의 성능이 저하되며 어느 시점부터는 테이블 전체 스캔보다 성능이 저하된다.

테이블 전체 스캔은 인덱스 스캔 후 테이블에 엑세스하는 방식처럼 ROWID 값으로 테이블에 엑세스하여 원하는 데이터를 추출하는 방식이 아니다.

테이블의 처음부터 끝까지 차례대로 엑세스하기 때문에 ROWID 값을 이용하지 않게 되며, 그러므로 랜덤 엑세스가 발생하지 않는다.

----

BY INDEX ROWID 실행 계획은 랜덤 엑세스를 의미한다.

실행 계획에서 BY INDEX ROWID나 BY LOCAL INDEX ROWID와 같은 형태는 반드시 랜덤 엑세스를 발생시킨다.

----

인덱스에 엑세스하는 방식을 이용할 것인지 아니면 테이블을 전체 스캔하는 방식을 선택할 것인지는 추출하려는 데이터의 양에 의해 결정될 것이다.

----

랜덤 엑세스에 의한 성능 저하는 I/O와 밀접한 관련이 있다.

인덱스에 엑세스하면 ROWID를 제공받는다.

100,000개의 블록으로 구성된 테이블이 있다고 가정하자.

인덱스로부터 100,000개의 ROWID를 제공받았다면 테이블에 대해 100,000번의 랜덤 엑세스를 수행해야하며, 해당 데이터들이 동일 블록에 존재할 가능성을 배제한다면 100,000번의 디스크 I/O를 발생시켜야 한다.

모든 데이터가 동일 블록에 있다면 메모리에서 엑세스가 발생할 것이다.

결국, 100,000건의 데이터에 대해서 인덱스 엑세스 후 ROWID 값으로 테이블에 엑세스한다면 디스크나 메모리에서 100,000번의 I/O가 발생한다.

테이블 전체 스캔은 테이블의 처음부터 끝까지 모든 데이터를 엑세스하는 실행 방식이다.

물론, 엑세스한 후에 필요없는 데이터에 대해서는 버리는 작업을 별도로 수행해야 한다.

하지만, 랜덤 엑세스처럼 ROWID 값에 의해 테이블에 엑세스하는 것이 아니므로 블록을 하나 하나 엑세스할 필요는 없다.

한 번의 I/O에서 여러 블록을 동시에 엑세스하기 위한 오라클 파라메터로 DB_FILE_MULTIBLOCK_READ_COUNT가 있다.

이 파라메터는 테이블 전체 스캔에서 한 번의 I/O 수행 시 동시에 엑세스하는 블록의 개수를 의미한다.

이 파라메터는 8, 16, 32, 64, 128로 설정된다.

128로 설정되어 있다면 전체 테이블 스캔 시 100,000개의 블록에 엑세스 하기 위해서 790번의 I/O가 발생한다.

----

많은 데이터에 대해 인덱스를 이용하며 엑세스하면 많은 양의 랜덤 엑세스가 발생하며, 랜덤 엑세스는 단일 블록 I/O를 수행하므로 엑세스하는 데이터 블록의 개수가 많다면 성능은 저하된다.

반면에 테이블을 전체 스캔한다면 다중 블록 I/O를 수행하므로 더 적은 I/O로 많은 데이터를 추출할 수 있다.

----

보통의 경우, 테이블의 3%~5% 미만에 대해서만 인덱스를 이용하는 것이 효과적이라고 말을 한다.

대용량의 테이블에 대해서는 1% 정도만 랜덤 엑세스해도 성능을 보장받기 힘들 수 있다.

인덱스 스캔 후 테이블에 엑세스하는 랜덤 엑세스가 증가한다면 어느 시점부터 테이블 전체 스캔 보다 성능이 저하된다.


2012년 10월 23일 화요일

실행계획 데이터베이스 튜닝 - 실행계획분석 10

힌트 주의점

1. 띄어쓰기, 대소문자 구별
2. 다중 힌트를 사용할 경우 의미상 모순
3. 테이블 명에 대한 별명(Alias)

하나의 힌트 절에 여러 개의 힌트를 동시에 설정할 수 있다.

힌트는 대소문자를 구별하지 않지만 각 힌트에 설정해야 하는 값들 중 테이블 이름은 대소문자를 구별한다.

FROM 절에 소문자로 테이블 이름을 정했다면 힌트에도 해당 태이블을 소문자로 설정해야한다.

모든 힌트 사이에는 반드시 한 칸씩 띄어쓰기가 들어가야 한다.

힌트를 사용할 때 테이블 별명을 사용하면 힌트 적용이 더 수월해진다.

----

실행 계획 확인 방법

EXPLAIN PLAN FOR
AUTOTRACE
TKPROF TRACE

----

AUTOTRACE

1. SET AUTOT ON - SQL을 실제로 실행한 후에 실행 계획 및 실행 중에 해당 SQL이 사용한 자원 등을 추출한다.

2. SET AUTOT TRACEONLY EXP - SQL을 실행하지 않으면 실행 계획 위주로 결과를 추출한다.

...

실행계획 데이터베이스 튜닝 - 실행계획분석 09

힌트로 실행 계획을 제어

문법이 틀려도 힌트가 SQL의 실행에 영향을 미치지는 않는다. 무시된다.

----

힌트 분류

1. 인덱스 엑세스 관련 힌트

2. 테이블 엑세스 관련 힌트

3. 조인 관련 힌트

4. 기타 힌트

5. SQL 변형 제어 관련 힌트

6. REMOTE 실행 계획 관련 힌트

----

인덱스 관련 힌트

INDEX

SQL이 엑세스 할 인덱스를 설정하는 힌트

INDEX(테이블이름, 인덱스이름) 형태로 사용

해당 테이블에 있는 인덱스 중에서 원하는 인덱스를 이용할 수 있게 해준다.

인덱스의 위에서부터 아래로 엑세스를 수행한다는 점에서 INDEX_ASC 힌트와 동일

오라클 10g에서는 INDEX(테이블이름, (컬럼이름, ..., 컬럼이름))으로도 설정 가능하다.

특정 인덱스를 설정하는 것이 아니라 해당 컬럼들로 구성된 인덱스를 유연하게 이용할 수 있게 해준다.

----

INDEX_DESC

인덱스를 구성하는 첫 번째 컬럼에 의해 내림차순으로 데이터가 추출

최근 데이터 순으로 추출하믄 목록 쿼리 또는 최대 값 및 최소 값을 추출하는 SQL에서 사용됨

----

INDEX_FFS

FAST INDEX FULL SCAN

일반 INDEX FULL SCAN과의 차이는 디스크 I/O 단위

INDEX_FFS(테이블이름, 인덱스이름)

NO_INDEX_FFS 사용 가능

----

PARALLEL_INDEX

INDEX_FFS 힌트와 동일, 여러 개의 프로세스로 인덱스 FULL SCAN

PARALLEL_INDEX(테이블이름, 인덱스이름, 프로세스개수)

NOPARALLEL_INDEX 사용 가능

----

INDEX_JOIN

2개 이상의 인덱스를 엑세스하여 테이블에 대한 랜덤 엑세스 없이 원하는 결과 데이터를 추출

하나의 테이블에서 데이터에 엑세스 하는 경우이므로 두 인덱스에 대한 조인 조건이 ROWID만 존재하므로 중첩 루프 조인을 사용한다면 성능이 저하된다. 그래서 오라클에서는 인덱스 조인 시에 해쥐 조인만 제공한다.

INDEX_JOIN(테이블이름, 인덱스이름)

----

INDEX_SS

INDEX_SS(테이블이름, 인덱스이름)

NO_INDEX_SS 사용 가능

INDEX_SS_DESC, INDEX_SS_ASC 사용 가능

인덱스의 철 번째 컬럼이 WHERE 조건 절에 설정되지 않고 첫 번째 컬럼의 분포도가 좋지 않아 몇가지 종류의 데이터만 저장될 경우 성능 향상 가능.

----

테이블 엑세스에 대한 힌트

분포도가 나쁘다는 것은 해당 컬럼에 동일한 값을 갖는 데이터가 많다는 의미다.

분포도가 나쁠 경우 해당 인덱스를 이용하는 순간 처리 범위가 증가하기 때문에 테이블의 많은 부분에 엑세스 해야 한다. 이로인해 증가하는 랜덤 엑세스는 엄청난 성능 저하를 발생한다. 따라서 분포도가 좋지 않은 인덱스를 이용하지 못하게 하고 테이블을 전체 스캔하는 것이 성능적인 면에서 더욱 유리하다.

인덱스를 이용하지 못하게 하는 방법에는 여러가지가 있으며, 그 중 하나가 FULL 힌트

FULL(테이블이름)

----

조인 관련 힌트

USE_NL

중첩 루프 조인을 수행

USE_NL(테이블이름, 테이블이름)

앞에 설정한 테이블에 먼저 엑세스, 뒤에 설정한 테이블은 뒤에 엑세스하여 중첩 루프 조인 수행

----

USE_HASH

해쉬 조인 수행, USE_NL 과 동일

----

USE_MERGE

소트 머지 조인, USE_NL 과 동일

----

NL_SJ - 중첩 루프 조인, 세미 조인

NL_AJ - 중첩 루프 조인, 안티 조인

HASH_SJ - 해쉬 조인, 세미 조인

HASH_AJ - 해쉬 조인, 안티 조인

MERGE_SJ - 소트 머지 조인, 세미 조인

MERGE_AJ - 소트 머지 조인, 안티 조인

----

조인 순서에 대한 힌트

ORDERED

두 개 이상의 테이블을 조인할 경우 어느 테이블이 먼저 엑세스 될지는 여러 개의 우선 순위를 확인하여 결정

모든 우선 순위가 동일하다면 FROM 절의 테이블의 역순

FROM 절에 설정한 순서로 테이블에 엑세스하여 조인하고 싶으면 ORDERED 힌트

매우 강력한 힌트로 옵티마이져는 이 힌트를 거의 무시하지 않는다.

----

LEADING

해당 힌트에 설정하는 테이블 순서에 의해 조인 순서가 결정

ORDERED 힌트와 함께 사용한다면 ORDERED 힌트가 우선시 된다.

/*+ LEADING(B, A) */

....

기타 힌트 생략 ...

실행계획 데이터베이스 튜닝 - 실행계획분석 08

데이터 연결 실행 계획

조인 실행 계획

1. 중첩 루프 조인 (NESTED LOOP JOIN)
2. 해쉬 조인 (HASH JOIN)
3. 소트 머지 조인 (SORT MERGE JOIN)

조인 실행 계획에서 조금씩 변형된 FILTER, SEMI, 카테시안, ANTI 조인 등이 존재한다.

순환 전개 실행 계획

CONNECT BY ... START WITH 구문으로 작성한 SQL 등에서 수행된다.

이외에도 데이터를 연결하는 방법에는 서브쿼리, 스칼라 서브쿼리, 인라인 뷰 등이 있다.

----

복합 실행 계획

실행 계획을 해석하는 방법

1. 가장 안쪽에 들여쓰기가 된 실행 계획부터 해석
2. 동일하게 들여쓰기가 된 실행 계획은 위에서부터 해석
3. 연관된 실행 계획은 함께 해석
4. 조인의 경우는 조인의 수행 방식으로 해석

실행계획 데이터베이스 튜닝 - 실행계획분석 07

STOPKEY 실행 계획

STOPKEY 실행 계획은 ROWNUM 연산자를 사용했을 경우 생성되는 실행 계획.

다른 실행 계획보다 우선 순위가 높다.

실행 계획에 테이블 전체 스캔이 생성되었다고 하더라도 ROWNUM 연산자가 있는 경우 STOPKEY 실행 계획이 수행되어 ROWNUM 조건을 만족하면 테이블의 스캔을 종료한다.

ROWNUM 연산자를 사용할 경우 인덱스의 이용이 매우 중요하다.

인덱스를 이용한 실행 계획이 아니면 얼마만큼의 데이터에 엑세스해야 하는지 정확히 알 수 없다.

인덱스를 이용한 실행 계획이라면 무조건 ROWNUM 이하의 데이터만 엑세스하게 되어 확실한 성능을 보장받을 수 있다.

ROWNUM 연산자가 SELECT 절에 사용된다면 실행 계획에슨 COUNT 실행 계획이 생성된다.

하지만, ROWNUM 연산자가 WHERE 절에 사용되었다면 COUNT(STOPKEY) 실행 계획이 생성된다.

----

파티션 실행 계획 - 생략

----

REMOTE 실행 계획 - 생략


실행계획 데이터베이스 튜닝 - 실행계획분석 06

집합 연산자에 의해 생성되는 실행 계획

UNION ALL - (A 합집합 B) + (A 교집합 B)
UNION - (A 합집합 B)
MINUS - (A 차집합 B)

UNION ALL을 제외한 모든 집합 연산자는 항상 UNIQUE 값을 추출한다.

UNIQUE 한 값을 추출하기 위해서는 SORT(UNIQUE) 실행 계획을 이용한다. - 대용량의 정렬은 성능이 저하될 수 있다.

-----

UNION ALL 집합 연산자는 UNION ALL 실행 계획이 생성되며 CONCATENATION 실행 계획과 동일하다.

다른 집합 연산자와 달리 SORT(UNIQUE) 실행 계획이 생성되지 않는다.

----

UNION 집합 연산자

UNION ALL 집합 연산자와의 차이는 SORT(UNIQUE) 실행 계획의 유무 - 즉, 중복 데이터를 제거한다.

대용량의 데이터에 UNION ALL 집합 연산자와 UNION 집합 연산자를 사용한 것의 데이터가 동일하다면 반드시 UNION ALL 집합 연산자를 사용해야 한다.

----

MINUS 연산자는 두 집합에 대해 각각 UNIQUE 정렬을 수행한다. 각각 UNIQUE 정렬을 수행한 후에 동일한 데이터를 제외한다.

안티 조인과 MINUS 연산자는 데이터의 속성에 따라 동일한 결과를 추출할 수도 있고 아닐 수도 있다.

두 개의 집합이 UNIQUE 한 값이라면 안티 조인과 동일한 결과가 추출될 것이다. 이러한 경우에는 안티 조인이 유리한 경우가 많다.

MINUS 연산자는 SORT(UNIQUE) 실행 계획에 의해 정렬을 수행하므로 시스템 자체의 자원을 많이 사용한다. 특히, 디스크 I/O와 관련해서 많은 자원을 사용할 것이다.

----

VIEW 실행 계획

VIEW 실행 계획은 VIEW 실행 계획 밑에 있는 테이블이나 인덱스에 엑세스하여 메모리에 임시 집합을 생성한다.

데이터에 한 번 엑세스한 후에 해당 데이터를 가공하는 부분에서는 VIEW 실행 계획이 생성된다.

FROM 절 안에 있는 완전한 SQL에 의해 VIEW 실행 계획이 생성될 수 있다.

하지만 FROM 절의 SQL이 별도로 수행되는 것이 아니라 해당 SQL이 하나로 합쳐져서 수행될 수 있다. 이렇게 수행된다면 VIEW 실행 계획은 생성되지 않는다.

VIEW 실행 계획에서 추출된 데이터는 메모리에 저장되며, 그러므로 인덱스가 존재할 수 없다. 그렇기 때문에 VIEW 실행 계획으로 만들어진 집합과 다른 집합이 조인을 수행하게 되면 VIEW 실행 계획에서 만들어진 집합에 전체 스캔이 수행될 수도 있다. 이러한 현상은 SQL의 성능을 좌우한다.

실행계획 데이터베이스 튜닝 - 실행계획분석 05

IN 연산자는 2가지 형태로 실행 계획이 생성될 수 있다.

우선 IN 연산자에 상수가 사용되는 경우만 살펴본다.

CONCATENATION

INLIST

--------------------------------------

CONCATENATION 실행계획

UNION ALL 집합 연산자와 동일한 개념의 실행 계획


SELECT /*+ RULE*/
*
FROM SEND_FILE
WHERE BASE_DATE IN ('20121022', '20120102')
;


SELECT STATEMENT   Cost =
    CONCATENATION
        TABLE ACCESS BY INDEX ROWID SEND_FILE
            INDEX RANGE SCAN SEND_FILE
        TABLE ACCESS BY INDEX ROWID SEND_FILE
            INDEX RANGE SCAN SEND_FILE

위의 실행 계획은 테이블에 엑세스를 두번하여 데이터의 합집합을 추출

IN 절에 인덱스가 이용되면 뒤에서부터 데이터가 추출된다.

---------------------------------------

INLIST 실행계획

SELECT
*
FROM SEND_FILE
WHERE BASE_DATE IN ('20121022', '20120102')
;

SELECT STATEMENT   Cost = 590
    INLIST ITERATOR   
        TABLE ACCESS BY INDEX ROWID SEND_FILE
            INDEX RANGE SCAN SEND_FILE

INLIST 실행 계획은 IN 절에 상수가 몇 개일지라도 테이블에 한 번만 엑세스한다.

------------------------------------------

IN 절이 인덱스를 이용할 경우
INLIST 실행계획은 IN 절의 앞에서부터 데이터를 엑세스하고 추출
CONCATENATION 실행계획은 IN 절의 뒤에서부터 데이터를 엑세스하고 추출

ROWNUM 연산자가 사용될 경우 ROWNUM <= 1
INLIST 실행 계획으로 생성될 경우 1건만 추출
CONCATENATION 실행 계획으로 생성될 경우 만족하는 모든 데이터를 추출한 후에 1건의 데이터만 추출하므로 성능이 저하됨

/*+ NO_EXPAND */ 힌트를 이용하면 CONCATENATION 실행 계획이 생성되지 않는다.

/*+ USE_CONCATE */ 힌트를 이용하면 CONCATENATION 실행 계획이 생성된다.

-------------------------------------

인덱스를 이용하지 못할 경우 IN 연산자는 테이블 전체 스캔




2012년 10월 22일 월요일

20121022 운동


스트레칭
  • 팔 스트레칭
  • 코브라 자세
  • 다리 자세
  • 물고기 자세
  • 고양이 자세
  • 낙타 자세
  • 반달 자세
맨손운동
  • 복근운동 상체들기 - 다리들기 각 10회 3 set
  • 브릿지 40초, 40초, 40초
트레드밀
  • 6 - 5분
  • 7.5 - 10분
  • 4 - 5분

트레드밀 후 다리 스트레칭
벽 밀기
서서 몸통 굽히기

딥 작게 5회 2set
- 팔, 어께 힘이 너무 약해 제대로 자세가 안나온다.
- 꾸준히 해보자.


다음 운동은 20121025

추가할 운동

허리운동
팔굽혀펴기


ps. 운동카드 반납 완료.

실행계획 데이터베이스 튜닝 - 실행계획분석 04


정렬 관련 실행 계획

1. SORT(AGGREGATE)
2. SORT(UNIQUE)
3. SORT(GROUP BY)
4. SORT(ORDER BY)

--------------

1. SORT(AGGREGATE)

SUM, MIN, MAX, COUNT 같은 집할 함수를 사용할 경우 생성.

----------------

2. SORT(UNIQUE)

IN 절을 사용할 경우 우일한 데이터를 만드는 정렬 작업이 내부적으로 발생할 수 있다.

IN 절이 먼저 수행되어 주 쿼리로 값을 제공할 경우에만 IN 절에서 SORT(UNIQUE)실행 계획이 생성된다.

IN 절이 뒤에 수행되어 데이터를 확인하는 경우에는 SORT(UNIQUE) 실행 계획이 생성되지 않는다.

DISTINCT 옵션을 사용할 경우에도 UNIQUE 정렬을 수행한다.

...


실행계획 데이터베이스 튜닝 - 실행계획분석 03

INDEX SKIP SCAN과 MIN/MAX SCAN은 오라클 9i 부터 도입된 실행계획


INDEX SKIP SCAN


MIN/MAX 실행계획

최소값 최대값을 추출하기 위한 SQL
보통 조건을 만족하는 모든 집한에 엑세스하여 정렬을 수행한 후에 최대 값이나 최소 값을 추출
아니면 INDEX RANGE SCAN DESCENDING 실행 계획을 이용하여 추출

SELECT
MAX(DURATION)
FROM  CDCP_ORG_PRICE A
WHERE REVAL_DATE = '20121018'
;


SELECT STATEMENT   Cost = 1734
    SORT AGGREGATE
        TABLE ACCESS BY INDEX ROWID CDCP_ORG_PRICE
            INDEX RANGE SCAN CDCP_ORG_PRICE_PK






SELECT
/*+ INDEX_DESC(A, CDCP_ORG_PRICE_PK) */
MAX(DURATION)
FROM  CDCP_ORG_PRICE A
WHERE REVAL_DATE = '20121018'
AND ROWNUM <= 1
;



SELECT STATEMENT   Cost = 1734
    SORT AGGREGATE
        COUNT STOPKEY
            TABLE ACCESS BY INDEX ROWID CDCP_ORG_PRICE
                INDEX RANGE SCAN DESCENDING CDCP_ORG_PRICE_PK

INDEX RANGE SCAN DESCENDING 실행 계획은 인덱스 스캔에서 발생하는 실행계획
인덱스 범위 스캔을 수행하는 과정에서 인덱스의 밑에서부터 엑세스하는 실행 계획
인덱스의 밑에서부터 엑세스하므로 해당 인덱스의 첫 번째 컬럼이 최대 값이 된다.

-----------------


INDEX JOIN도 인덱스 스탠의 한 종륲다.

1+3 인덱스와 2+4 인덱스가 있을 때, 1, 2가 WHERE 절에 포함되고, 3, 4가 SELECT 절에 포함되면 테이블에 대해 랜덤 엑세스 없이 원하는 모든 값을 추출할 수 있다.

인덱스 조인은 반드시 해쉬 조인으로만 수행된다.

1+3, 4+2 인덱스가 있는 경우 WHERE절에서 1, 2 조건, SELECT 절에서 3, 4 조회일 경우 인덱스 조인으로 수행

2012년 10월 16일 화요일

20121016 운동

스트레칭

  • 팔 스트레칭
  • 코브라 자세
  • 고양이 자세
  • 낙타 자세

맨손운동
  • 복근운동 상체들기 - 다리들기 각 10회 3 set
  • 브릿지 30초, 40초
  • 팔굽혀 펴기 5회
트레드밀
  • 6 - 5분
  • 7.5 - 10분
다음 운동은 20121018

추가할 운동

다리 자세
물고기 자세
반달 자세

트레드밀 후 다리 스트레칭
벽 밀기
서서 몸통 굽히기


운동도 공부해야한다. 공부하자!

ps. 운동카드 반납 완료.

20121015 운동


10분 스트레칭
누워서 허리 운동
무릅 굽히고 복근운동 - 다리 들기 10회 2 set

25분 트레드밀
5분 5
20분 6.5
5분 4

다리 스트레칭

허리들기 10회

sap 사이트를 뒤지고 읽고 정리하자.

실행계획 데이터베이스 튜닝 - 실행계획분석 01

계획
20121022 ~ 20121026 ch1
20121029 ~ 20121102 ch2
20121105 ~ 20121109 ch3
20121112 ~ 20121116 ch4
20121119 ~ 20121123 ch5, ch6
20121126 ~ 20121130 ch7

SQL을 통해 결과를 추출하는 과정에서 여섯 가지 방법을 함께 이용할 수 있다.

실행계획 6가지

1. 테이블 관련 실행 계획

2. 인덱스 관련 실행 계획

3. 정렬 관련 실행 계획

4. 연산자 관련 실행 계획

5. 데이터 연결 관련 실행 계획

6. 파티션 관련 실행 계획

-----------------------------

테이블 관련 실행 계획

1. BY INDEX ROWID - 인덱스 스캔을 통한 테이블 엑세스

2. FULL SCAN - 테이블 전체 스캔

3. BY USER ROWID - 정의된 ROWID에 의한 테이블 엑세스

4. SAMPLE - 표본 데이터 추출

테이블의 컬럼에 인덱스가 존재한다면 해당 인덱스에 엑세스하는 순간 인덱스로부터 ROWID가 제공된다.

ROWID는 하나의 데이터를 찾아가는 유일한 주소

인덱스를 이용하지 않고 테이블에 바로 엑세스한다면 FULL SCAN

CONNECT BY 절을 사용하면 BY USER ROWID 실행 계획

BY INDEX ROWID와 FULL SCAN이 주로 사용됨

-----------------------------

인덱스를 이용한 후에 테이블에 엑세스하면 BY INDEX ROWID 실행 계획이 생성된다.

인덱스에서 생성되는 실행 계획은 9가지

1. INDEX RANGE SCAN

2. INDEX UNIQUE SCAN

3. INDEX AND-EQUALS

4. INDEX FULL SCAN

5. INDEX FAST FULL SCAN

6. INDEX PARALLEL SCAN

7. INDEX SKIP SCAN

8. INDEX MIN/MAX SCAN

9. INDEX JOIN

-------------------------------

선분조건 LINE CONDITION 이 사용된 WHERE 조건의 컬럼이 인덱스를 이용할 경우 INDEX RANGE SCAN이 발생

점조건 POINT CONDITION 일지라도 인덱스를 UNIQUE 인덱스로 생성하지 않았다면 INDEX RANGE SCAN

값을 만족하는 데이터가 세 건이라면 실제 데이터 엑세스는 네 번 이루어진다.

-------------------------------

점 조건 중에서 = 조건을 사용하며 해당 조건에서 UNIQUE 인덱스를 이용하면 INDEX UNIQUE SCAN

UNIQUE 인덱스이더라도 점 조건이 아닌 선분 조건으로 조회된다면 INDEX RANGE SCAN

-------------------------------

보통의 경우 INDEX AND-EQUALS 실행 계획은 성능 최적화 대상이 될 수 있다.

8i에서 도입 10g 부터 폐기

INDEX AND-EQUALS 실행 계획은 두 개의 인덱스를 이용하여 원하는 데이터를 추출

두 컬럼의 인덱스를 추출하여 인덱스 머지를 수행

인덱스 머지
각 인덱스에서 조건을 만족하는 데이터의 ROWID를 확인한 후 1번 인덱스에서 조건을 만족하는 값을 찾으면 확인한 ROWID를 2번 인덱스에서 동일한 ROWID가 확인될때까지 찾는다. 2번 인덱스에서 값을 다 확인한 후 다시 1번 인덱스로 돌아가 다음 값이 조건을 만족하는지 확인한다. 그리고 반복한다.

결합 인덱스를 이용한다면 처리 범위가 감소할 수 있다.

INDEX AND-EQUALS 실행 계획이 빈번히 발생한다면 인덱스 선정을 다시 검토해야 한다.

--------------------------------

DB 실행계획에 대해 공부중이다.

공부한 내용을 요약하면서 다시 한번 상기중인데 양이 많다. 정말 많다.

아무든 계속.

덴마 1. 파마나의 개

DENMA THE QUANX

네이버에 연재되고 있는 웹툰이다.

연재된지는 꽤나 오래된 것 같은데 손이 잘 가지않아 안보고 있었다.

작가는 양영순 님이다.

누들누들부터 시작해 인기작품을 꽤나 많이 그리셨던 작가로 기억한다.

천일야화도 정말 재밌게 보았었다.

서론은 여기까지 하고.

QUANX, 퀑이라고 작품상에서 발음된다.

기존에 있던 단어인지 작가의 조어인지는 모르겠으나 작품상에서는 특이한 능력, 즉 초능력을 가지고 있는 사람은 퀑이라고 부른다.

사람이라고 단정짓기는 어렵겠다. 사람뿐만 아니라 여러 생명체가 나오고 이 중 초능력이 있는 자들의 통칭으로 퀑이라고 한다.

덴마도 역시 퀑이다. 덴마의 능력은 질량등가치환.

공간좌표만 확인되면 무엇이든 손에 들고있는 것의 질량만큼 맞바꿀 수 있다.

(얼핏봐도 정말 사기캐다;; 무궁무진하게 활용할 수 있는 능력인듯.)

덴마는 이 능력을 가지고 실버퀵이라는 택배회사(ㅋㅋ)에 직원으로 일하고 있다.

물론 본인이 택배회사를 선택한 것은 아니고 사기, 납치를 당해 본인의 몸이 아닌 다른 몸에 정신이 옮겨져 있다.

영혼이 옮겨진 것인지, 전뇌? 같은 설정으로 다른 육체를 사용하고 있는지는 잘 모르겠다.

아직 초반이라 전개된 내용은 잘 모르겠지만 에피소드 형식으로 진행되고 모든 에피소드를 관통하는 하나의 큰 흐름이 있는 듯 하다.

탄탄한 세계관이 구축되어 있고 2개정도의 에피소드만 봤지만 앞으로의 내용이 정말 흥미진진할 것 같다.

기대되는 웹툰.

에피소드 1. 파나마의 개의 명장면


이런 전개 완전 좋다.

아버지의 얼굴 표정의 흐름이 한눈에 보이면서 인생의 후회가 단 몇 마디에 압축되어있는 화면.

무뚝뚝했던 우리의 아버지들이 연상되는 그런 구도.

중언부언 길게 말할 수도 있겠지만 " 미안하다. 더... 더 행복해지려고 했는데... 잘 안됐어."

이 짧은 말이 진한 여운을 남긴다.

좋구나! 덴마. 앞으로 꾸준히 감상글을 남겨보겠다.


2012년 9월 21일 금요일

Oracle Enterprise Manager 간략 사용기 2

http://tryinsights.blogspot.kr/2012/09/oracle-enterprise-manager-1.html 글에 이어 두번째.

Oracle Enterprise Manager로 AWR(Automatic Workload Repository), ASH(Active Session History) 리포트를 작성하는 방법.

AWR

Database Instance(데이터베이스 인스턴스)화면에서 Administration(관리) 탭을 선택.
Database Administration(데이터베이스 관리) -> Statistics Management(통계 관리) -> Automatic Workload Repository(자동 작업 로드 저장소)를 선택.

Manage Snapshots and Preserved Snapshot Sets(스냅샷 및 보관된 스냅샷 집합 관리) 항목에서 현재 EM이 보유하고 있는 Snapshot이 몇개 있는지 확인 할 수 있다.

Snapshot(스냅샷) 의 숫자를 클릭하면 Snapshot 화면이 나타난다.
Select Beginning Snapshot(시작 스냅샷 선택) 화면 에서 Action(작업)을 View Report(보고서 보기)로 선택하고 Beginning Snapshot 을 선택하고 Go(실행) 버튼을 누른다.
(Create(생성) 버튼이 아니다.)

View Report(보고서 보기) 화면 -> Select Ending Snapshot(종료 스냅샷 선택) 화면에서 Ending Snapshot 을 선택하고 OK(확인) 버튼을 누른다.
(Go(실행) 버튼이 아니다.)

잠시 후에 AWR Report 가 생성되고 Save to File(파일에 저장) 버튼으로 저장할 수 있다.


ASH

현재 데이터베이스 인스턴스 성능에 관련된 정보를 주기적으로 볼 수 있는 화면으로, 인스턴스 성능에 영향을 줄 수 있는 CPU 사용률, 활성화된 세션수, 디스크 입출력 등을 확인 할 수 있다.
Database Instance(데이터베이스 인스턴스) -> Performance(성능) 탭 선택.
Run ASH Report 버튼 클릭.

Run ASH Report 화면에서 Start Date, Start Time, End Date, End Time 을 선택 후 Generate Report 버튼 클릭

2012년 9월 20일 목요일

Oracle Enterprise Manager 간략 사용기 1

oracle 10g 버전에서 Oracle EM을 사용해봤다.

사용경험을 간단히 적어본다.

로그인을 하면 첫 화면에 굵직한 항목들이 보인다.

가장 자주보게 될 것 같은 화면은 "데이터베이스 인스턴스(Database Instance)" 화면에 있는 "성능(Performance)" 탭이다.

다음과 같은 그래프를 확인 할 수 있다.

Host 그래프 : 호스트의 CPU 평균부하
Average Active Sessions 그래프 : Active Session의 Wait 상태정보
Instance Disk I/O : Instance에서 사용중인 Disk I/O 상태
Instance Throughput : Instance Throughput 상태

Active Sessions 그래프에서 가장 많은 면적을 차지하는 CPU Used 항목을 선택하면 상세정보를 보여준다. 시간대 별로 Top SQL과 Top Session 정보를 확인할 수 있다.


Average Active Sessions 그래프를 보여주는 화면에서 ADDM을 사용할 수 있다.

Run ADDM Now 버튼을 누르고 다시 확인 버튼을 누르면 Average Active Sessions 그래프의 특정 시간대를 선택할 수 있는 화면이 나타난다. 특정 시간대를 선택하면 하단의 Performance Analysis 창에 성능문제 요소와 각 요소별 영향도와 권장 사항을 요약하여 보여준다.

Performance Analysis 창에서 영향(Impact)가 높은 항목을 선택하면 세부 정보 화면이 나타난다. 세부정보 화면에서는 권장사항을 확인 할 수 있다. "모든 세부 정보 표시(Show All Details)를 선택하고 그 중  이익률(Benefit)이 가장 높은 항목의 "지금 권고자 실행(Run Advisor Now)를 클릭한다. "SQL 튜닝 권고자 일정잡기(Schedule SQL Turning Advisor)"  버튼을 클릭하여 원하는 시점에 시작할 수 있게 설정할 수 있다.

일정시간이 지나면 Recommendations 화면이 나타난다.
이 화면에서 View Recommendations 버튼을 클릭하여 SQL 튜닝 결과를 확인한다. 튜닝 결과 새로운 실행계획과 Benefit이 %로 나타난다. 튜닝된 실행계획은 기존 실행계획과 비교할 수 있다.

해당 화면에서 Implement 버튼을 클릭하면 튜닝된 실행계획을 적용시킨다.

(실제로 Implement 버튼을 클릭해 튜닝된 실행계획을 적용시켜 보지는 못했다-_-;)

Solaris 가상메모리

Solaris는 가상메모리 시스템을 사용한다.

가상메모리 시스템이란 물리적 메모리와 하드디스크를 결합하여 하나의 큰 메모리 처럼 사용하는 것을 말한다.

물리적 메모리 + 스왑 디바이스 - VM management overhead = swap (VM)

(물리적 메모리 + 스왑 디바이스) * about 90% = swap(VM)

솔라리스는 가상메모리를 관리하기 위해 메모리를 페이지 단위(8k)로 나누어 관리한다.

(페이지 size는 pagesize로 확인한다.)

이러한 페이지를 모아서 세그먼트로 구성하여 사용한다. 프로세스가 동작하기 위해서는 그 프로세스가 필요한 메모리가 있다. 그러나 그 메모리가 물리적 메모리에 모두 적재되어야 실행되는 것은 아니다. 프로세스가 실제 엑세스하는 메모리만 물리적 메모리에 적재되어 있이도 프로세스는 실행된다. 구론대 여유있는 물리적 메모리가 없어서 프로세스에게 필요한 메모리를 줄 수 없을 때 커널은 현재 사용하고 있는 물리적 메모리 중에 최근에 사용되지 않은 메모리를 선택하여 그 메모리를 프로세스에게 준다.

Solaris에서는 가상메모리를 swap으로 부른다.(swap partition과 구별) 이 swap(VM)은 운영체제가 사용할 수 있는 메모리다. vmstat 명령어의 4번째 필드 swap은 사용가능한 가상메모리의 크리를 KB 단위로 나타내고 5번째 필드 free는 사용 가능한 물리적 메모리를 KB 단위로 나타낸다.

가상메모리에 대한 자세한 내용은 swap -s 명령어로 알 수 있다.


# swap -s
총: 7033864k 바이트 할당 + 868672k 예약 = 7902536k 사용, 21814816k 사용 가능

할당 받은 것과 예약된 것의 차이는 다음과 같다.

만일 프로세스가 데이터를 관리하기 위해 10MB의 메모리가 필요하여 요청했다면 10MB의 메모리가 그 프로세스가 사용할 수 있도록 예약해 둔다. 그리고 그 포로세스가 메모리를 실재 엑세스 할때 그 메모리가 할당된다. 예를 들어 10MB메모리를 요청하여 1MB의 메모리만 엑세스했다면, 1MB는 할당된 영역에 더해지고, 9MB는 예약된 영역에 더해진다.

응용 프로그램이 동작할때 필요한 메모리는 swap(VM)에서 가져온다. 물리적 메모리가 많든 적든 관계없이 swap 공간이 충분하면 프로그램이 실행되는데에 전혀 문제가 없다. 만일 물리적 메모리가 절대적으로 부족하다면, 실행속도가 늦어질 뿐, 메모리 부족으로 응용 프로그램이 중단되는 일은 없다.


swap partition에 대한 정보는 다음과 같이 swap -l 명령어로 확인 할 수 있다.

# swap -l
swapfile             dev  swaplo 블록   사용 가능
/dev/dsk/c0t0d0s1   32,9      16 33560432 33560432
총 swap partition은 약 16GB

블록은 전체 swap partition의 크기이며 512byte 단위다. free는 그 중 사용가능한 swap partition의 크기이면 역시 512byte 단위의 블록이다.


추가예정

사용가능한 가상메모리는 다음과 같이 확인 할 수 있다.


# swap -s
총: 7062496k 바이트 할당 + 886584k 예약 = 7949080k 사용, 21768576k 사용 가능

# vmstat 1 3
 kthr      memory            page            disk          faults      cpu
 r b w   swap  free  re  mf pi po fr de sr s1 s3 s9 sd   in   sy   cs us sy id
 0 0 0 22635688 8170192 1242 405 24166 0 0 0 0 2 54 -0 26 2151 9478 6393 7 9 83
 0 0 0 21777592 7594664 14 59 98 0 0  0  0  0  0  0  0  910 16713 2362 8  4 87
 0 0 0 21777464 7594672 13 35 16 0 0  0  0  0  0  0  0  790 5809 1648  2  2 95

# sar -r 1 3

SunOS newbluewin01 5.10 Generic_137111-01 sun4u    09/20/2012

15:22:49 freemem freeswap
15:22:50  949502 43555856
15:22:51  949500 43555856
15:22:52  950901 43555856

Average   949968 43555856


swap -s : 21768576k(약20G)
vmstat 1 3 : 21777464 
sar -r 1 3 : 43555856(block) * 512(byte) /1024 = 21777928

사용가능한 물리적 메모리는 vmstat의 free(KB)와 sar -r 의 freemem(page)에서 확인할 수 있다.

vmstat 1 3 : 7594672 (약 7G)
sar -r  1 3 : 949968 * 8192 = 7599744




ksar 사용법 정리

서버 성능 측정을 위해 sar를 열심히 찾아보다가 ksar 라는 것을 발견했다.

sar 데이터를 그래프로 나타내 주는 프로그램인데 사용법을 알아두면 유용할 것 같아 정리해 둔다.

일단 홈페이지는 여기.

http://sourceforge.net/projects/ksar/

다운 받아 압축을 풀어보면 몇개의 폴더와 파일이 나오는데 윈도우에서 실행하려면 그 중 kSar.jar 파일을 실행하면 된다.

ssh를 통해 서버에 접속하여 사용할 수도 있고 서버에서 데이터를 만들어 결과 파일을 import 할 수도 있다.

물론 서버에 직접 설치할 수도 있지만 운영서버에 그러고 싶지는 않아서-_-; 선택한 방법은 데이터 파일을 만들어 kSar 프로그램에 import.

아래 내용은 Solaris10 기준이다.

/usr/lib/sa/sa1 를 입력하면 /var/adm/sa 경로에 sa[dd] 파일이 생성된다.

[dd]는 해당 날짜를 의미한다.

sa[dd] 파일은 이진파일이어서 vi 등으로 데이터를 확인할 수 없다.

sar -A -f sa[dd] > output 커맨드를 이용해서 sa[dd]의 데이터를 text로 output 파일에 기록한다

생성된 output 파일을 ftp 등으로 kSar 프로그램이 설치된 PC로 옮기고 Data -> Load from text file 메뉴를 선택하여 output 파일을 import 한다.

/usr/lib/sa/sa1 커맨드를 한 번만 실행한 데이터를 output 파일로 만드니 output 파일에는 데이터가 포함되어있지 않은 것 처럼 보였다.

/usr/lib/sa/sa1 커맨드를 한 번 더 실행하고 output 파일을 생성하자 데이터가 보이기 시작했다.

원인은 정확히 모르겠지만 일단 무시하고...

/usr/lib/sa/sa1 커맨드를 여러번 실행하면 실행 한 횟수만큼의 데이터가 sa[dd] 파일에 누적됨을 확인했다.

cron을 이용하여 /usr/lib/sa/sa1 을 5분마다 실행되도록 설정했다.

0,5,10,15,20,25,30,35,40,45,50,55 * 20 9 * /usr/lib/sa/sa1

일단 테스트를위해 9월 20일에만 동작하도록 설정.

생성된 데이터를 kSar에서 확인해보니 그래프가 잘 나온다.

그래프의 의미를 해석하기 위해서는 계속 sar에 대해 공부가 필요할 듯 하다.

몇 일 테스트 해보고 이상이 없으면 output 파일을 만들고 ftp로 local로 전송하는 script와 sa[dd] 파일도 누적되어 디스크가 full 이 되지않도록 주기적으로 삭제하는 script를 만들어야겠다.


2012년 9월 19일 수요일

vmstat 분석(계속)

kthr memory page disk faults cpu
r b w swap free re mf pi po fr de sr s1 s3 s9 sd in sy cs us sy id
0 0 0 22638296 8172808 1241 405 24149 0 0 0 0 2 53 0 26 2152 9484 6396 7 9 83
0 0 0 21628528 7539648 1627 339 97720 0 0 0 0 0 0 0 67 2661 2880 5891 2 16 82
0 1 0 21621808 7517128 1498 1111 86065 0 0 0 0 0 0 0 53 2402 4554 5399 4 22 75
0 0 0 21609336 7517464 1580 2496 48768 0 0 0 0 1 0 0 36 1712 13020 5071 5 21 73
0 0 0 21613832 7526624 1418 1474 45617 0 0 0 0 197 0 0 41 1834 11530 4156 7 26 67
0 1 0 21623768 7516480 4286 678 84617 0 0 0 0 0 0 0 101 3348 11121 6880 18 18 64
0 1 0 21612096 7486936 2695 740 62159 0 0 0 0 0 0 0 54 2080 5215 4141 26 12 62
0 1 0 21628088 7453264 2887 346 66606 8 8 0 0 0 0 0 42 2104 3405 4069 34 10 56
0 2 0 21629944 7418056 2479 1 65777 0 0 0 0 0 0 0 38 2096 8782 3927 8 9 83
0 3 0 21618144 7330424 7991 404 148917 0 0 0 0 0 0 0 121 4524 7762 10128 5 27 68

한 화면에 나타내기 정말 어렵다-_- 잘(?) 보자.

서버 성능 측정을 위해 vmstat 을 찾아보았다.

vmstat 은 CPU와 I/O를 모니터링 할 수 있다.

첫 줄은 부팅 이후 각 통계치에 대한 평균값이다.

kthr - kernel thread state change

proc로 표현되기도 한다.

대부분의 OS는 멀티스레드 기능을 제공하며, 커널의 스케줄링도 스레드 단위로 한다.

멀티스레딩 방식으로 프로그래밍 되지 않은 프로세스는 하나의 프로세스에 하나의 스레드만 있다.

thread state는 3가지가 있다.

1. CPU를 사용하고 있는 스레드.
2. CPU를 사용하기 위해 Run Queue에서 대기하고 있는 스레드
3. I/O나 이벤트가 완료되기를 기다리면 sleep 중인 스레드

vmstat kthr의 r, b,w 의 의미는 다음과 같다.

r - the number of threads in run queue
CPU를 사용하기 위해 Run Queue에서 대기하고 있는 스레드(2 이상이면 CPU busy)

b - the number of threads blocked for resources (I/O, paging, and so forth)
I/O나 이벤트가 완료되기를 기다리며 sleep 중인 스레드
CPU 성능과 관계없다고 판단.
Disk의 I/O가 느릴때 b의 수치가 증가한다.

w - the number of threads swapped out
swap out된 실행가능한 스레드(0 이상이면 메모리가 부족하다고 판단)
시스템의 메모리가 부족할 때 paging이 발생.
페이징으로도 부족한 메모리를 보충하지 못하면 swapping이 발생.
이때 메모리로 부터 빠져나가 swap 디바이스에 보관된 스레드의 개수를 w에 보여준다.
swap out 된 스레드는 대기 후 다시 실행될 때 메모리로 swap in 된다.

memory - Report on usage of virtual and real memory.


swap - amount of swap space currently available (Kbytes)
사용 가능한 가상 메모리(physical memory + swap device)의 크기.
평소에 이 값이 높다고 해도 free 메모리의 여유가 있다면 메모리가 부족한 것이 아니다.

free - size of the free list (Kbytes)
사용 가능한 physical memory 의 크기.


page - Report information  about  page  faults  and paging  activity. (second.)

이후의 부분은 다음에 다시 정리하자.

Server의 Memory 성능의 지표를 알고 싶었는데 부족한 느낌이다.


참고사이트
http://ldcc.tistory.com/entry/vmstat-%ED%95%84%EB%93%9C-%EC%84%A4%EB%AA%85

http://blog.naver.com/PostView.nhn?blogId=ares2011&logNo=50023242845&parentCategoryNo=28&viewDate=&currentPage=1&listtype=0

http://jikime.tistory.com/286

C# 프로그램 구상

C#을 이용한 간단한 FrameWork를 구상하고 있다.

기본기능은 로그인, 자동업데이트, 로그처리 등이다.

로그인 되면 DB에서 계정 정보를 확인하고 해당 계정에 허용된 메뉴를 보여준다.

그리고 허용된 메뉴에 대하여 자동 업데이트를 진행한다.

고민이 되는 부분

Frame 안에서 실행되는 각 화면 중 하나가 실행 중 다운되면 Frame 자체에 영향을 주어 프로그램 전체가 다운되는 현상이 발생할 것 같다.

한 Frame에서 여러 화면이 독립적으로 운영되도록 하고 싶은데 방법이 있을까?

로그인, 자동 업데이트 부분은 구글링을 하면 많은 자료가 나온다.

하나씩 구현해보자.

로그에 포함되어야 할 부분은 다음과 같다.

1. 화면 호출
2. DB와 관련된 UI 조작
3. 호출된 query
4. 호출된 query의 실행 시간
5. fatch 수행 시간
6. 모든 로그는 시각과 USER_ID 포함

로그파일은 프로그램이 종료될때 서버로 전송된다.

서버에 전송된 파일은 로그 파싱 프로그램을 통해 DB 로 저장된다.

로그들을 수집하여 분석하면 다음과 같은 결과를 얻을 수 있다.

1. 비효율적으로 동작하는 query
2. 사용자 조작 오류 - 제작 의도와 다르게 사용하는 것도 오류라고 판단한다.
3. 프로그램 동작 시간
4. 특정 시간에 동작하는 query
5. 긴 기간동안 query 수행시간의 변화 추이

넘어야할 산이 많다. 차근차근 진행해보자.

C# 기초강좌 1

네임스페이스에는 다섯가지 엔티티(entity)들이 계층적으로 정리되어 있다.

1. class
코드와 데이터를 캡슐화하는 기본적인 구성 요소

2. struct
.NET 구조체는 참조 타입이 아닌 값 타입.
클래스와 유사.
힙이 아닌 스택에 저장되면 작은 행목들을 저장하거나 배열에 자장되는 경우에 적합.
상속될 수 없다.

3. interface
클래스와 유사.
메서드를 갖지만 메서드 내에 정의된 코드는 없다.
클래스는 여러 개의 인터페이스를 상속받을 수 있다.
캐스팅에 유용.

4. delegate
대리자는 메서드 프로토 타입.

5. enum
상수값을 정의.

2012년 9월 14일 금요일

DB Server 자원을 많이 사용하는 프로세스 찾기(ps)

ps를 이용하여 DB 서버 자원을 많이 사용하는 프로세스를 찾기위해 다음과 같이 처리했다.

ps -ef -o user,pid,ppid,pcpu,vsz,etime,time,args | sort -r -k 4 | head -n 15

부연 설명을 하자면

ppid
Parent Process ID

pcpu
간단히 말해서 CPU 사용률

vsz
프로세스가 사용하고 있는 가상 메모리의 크기(KB)

etime
프로세스가 시작한 후 경과된 시간

time
CPU 사용시간


args
command

sort -r -k 4

-r
reverse

-k
keydef

참고
http://docs.oracle.com/cd/E23823_01/html/816-5165/ps-1.html#REFMAN1ps-1

PID, SID를 이용하여 oracle query 확인


DB Server의 Resource를 과도하게 사용하는 프로세스를 확인할 때 사용한다.

PID를 알고 있을 경우

SELECT S.USERNAME USERNAME, S.OSUSER, S.PROGRAM, T.SQL_TEXT SQL, T.PIECE
FROM V$SQLTEXT T, V$SESSION S,
  (SELECT S.USERNAME USERNAME, S.OSUSER OSUSER, S.PROGRAM PROGRAM
  FROM V$SESSION S, V$PROCESS P
  WHERE P.ADDR = S.PADDR
  AND   S.SID IN (
    SELECT S.SID
    FROM V$SESSION S,V$PROCESS P
    WHERE P.ADDR=S.PADDR AND P.SPID = 6166)
  ) U
WHERE T.ADDRESS = S.SQL_ADDRESS
AND   S.USERNAME = U.USERNAME
AND   S.OSUSER  = U.OSUSER
AND   S.PROGRAM = U.PROGRAM
ORDER BY PIECE
;


SELECT SQL_TEXT
FROM V$SQLAREA
WHERE HASH_VALUE = (
  SELECT S.SQL_HASH_VALUE
  FROM V$SESSION S, V$PROCESS P
  WHERE P.ADDR=S.PADDR AND P.SPID=6166
  );

SID를 알고 있을 경우


SELECT /*+ RULE ORDERED */
S.SID,
S.SERIAL#,
S.SQL_HASH_VALUE,
Q.SQL_TEXT
FROM V$SESSION S,
V$SQLTEXT Q
WHERE S.SQL_HASH_VALUE = Q.HASH_VALUE
AND S.SQL_ADDRESS = Q.ADDRESS
AND S.SID = 948
AND S.SQL_HASH_VALUE <> 0
ORDER BY S.SID, Q.PIECE
;

process 확인은 다음의 명령어를 사용했다.
ps -ef -o user,pid,ppid,pcpu,vsz,pmem,nlwp,etime,time,args | sort -r -k 4 | head -n 15



Oracle 관련 OS 튜닝 방법

조규형님의 마소 2002년 3월 기고글을 요약했다.

DB 성능 측정에 도움이 될 듯하다...?

솔직히 장담은 못하겠다 ㅠㅠ

데이터베이스 성능에 문제가 발생한 경우 해결방법
1. 시스템의 사양을 높이는 방법
2. 튜닝

성능 관리의 단계
1. 분석단계
2. 설계단계
3. 개발단계
4. 테스트와 운영단계

1. 분석단계
업무 프로세스의 최적화, 시스템 구조 설정, 용량 산정
대략적인 경험치를 이용해 산정

2. 설계단계
논리적 설계, 데이터의 물리적 설계
논리 설계시에 도출된 ERD를 기초로 구축하고자 하는 시스템의 구조와 성능을 고려해 물리적 설계를 해야함.
요구 응답시간, 분산 데이터베이스 환경, 동시 사용자의 수, 데이터의 크기, 병렬 프로세싱 등을 고려.

3. 개발단계
SQL을 효율적으로 작성
옵티마이저의 이해
인덱스 정책

4. 테스트, 운영단계
OS튜닝
네트워크 튜닝
데이터베이스 튜닝
애플리케이션 튜닝

----

개발, 테스트, 운영 단계에서 고려해야 하는 오라클과 연동한 OS, 네트워크 튜닝에 대해 알아보자.

OS튜닝
OS에는 CPU, 메모리, 디스크I/O가 대표적 튜닝 대상.
통상적으로 OS튜닝은 전체 성능의 10% 이상의 성능 향상을 기대하기 힘들다.
다른 부분의 튜닝을 끝내고도 만족할만한 성과가 나타나지 않을 때 자세한 OS 튜닝으로 좋은 효과가 나타나는 경우가 있다.

CPU튜닝
유닉스의 sar 명령을 이용해 CPU의 사용량을 볼 수 있다.



# date; sar 3 10
2012년 9월 14일 금요일 오후 01시 41분 55초

SunOS 5.10 Generic_137111-01 sun4u    09/14/2012

13:41:55    %usr    %sys    %wio   %idle
13:41:58       3       7       0      90
13:42:01       3       2       0      95
13:42:04       8       9       0      83
13:42:07      47      19       0      33
13:42:10      20      18       0      62
13:42:13      15      14       0      70
13:42:16      12       8       0      80
13:42:19       6       6       0      89
13:42:22       4       4       0      92
13:42:25       4       3       0      93

Average       12       9       0      79



CPU는 정상적인 운영 상태에서 권장하는 사용 정도는 70~80%.
시스템의 사용량이 많은 시점을 고려하여 20~30%의 idle time이 유지되어야 함.
idle이 0%라는 의미는 CPU를 100% 사용한다고 볼 수도 있겠지만, 100% 이상을 사용해 CPU의 병목현상이 발생한다고 판단.
CPU가 부족하다고 판단된 경우에는 문제시되는 부분을 찾아 해결하거나 CPU 증설을 고려.
CPU의 사용량이 과다하게 나타났을 경우라면 우선 %usr, %sys, %wio의 비율을 비교.
데이터베이스를 사용하는 애플리케이션이 운영되는 시스템일 경우에는 %usr > %sys > %wio의 순으로 나타나는 것이 정상적.

%wio의 수치가 가장 높게 나타날 경우에는 CPU의 사용이 I/O waiting을 위해 사용된다고 추정가능함.
I/O의 병목현상을 해소시켜 주거나 유닉스 파일 시스템의 오퍼레이팅 버퍼 캐시의 활용도를 높여주면 전체적인 CPU 사용량은 감소하게 됨.
버퍼 캐시의 활용도를 높여주는 것보다는, I/O를 분산시키는 것이 훨씬 효과적임.

%sys의 사용량이 높을 경우에는 정상적이지 않은 프로세스가 CPU를 많이 점유하는 경우. 이런 경우 현재 시스템에서 CPU를 많이 사용하는 프로세스를 찾아 원인을 분석.
(현재 Solaris에서는 top이 없어서 prstat으로 확인가능하다.)
프로세스 분석에서 주의 깊게 봐야하는 것은 %CPU, %MEM, TIME.
각각 CPU 점유율, 메모리 점유율, 자동 후 CPU의 누적된 사용치.
하나의 프로세스가 CPU 하나를 99%나 100%를 차지하고 오랜 시간(1분 이상) 사용할 경우 이프로세스가 어떤 프로세스인지, 그리고 어떤 작업을 하는지 파악해야 함.

메모리 튜닝
유닉스 시스템은 Physical 메모리의 한계를 극복하기 위해 버추얼 메모리 개념을 사용해 메모리를 운영하는데, 버추얼 메모리의 크기는 'Physical 메모리 + 버추얼 메모리(Swap disk)'다. 버추얼 메모리는 page의 집합으로 구성되며, page의 크기는 보통 4KB 또는 8KB이다. Page란 메모리는 나누는 단위인데, 가능한 한 많은 Free 메모리를 유지하기 위해 현재 사용하고 있지 않은 page를 disk로 저장한다(page-out). 만약 현재의 어떤 프로세스가 physical 메모리에 존재하지 않은 page를 요청하면(page fault) disk에 저장한 page를 메모리로 읽어 들인다(page-in).
Swapping은 간단히 설명하자면 paging보다는 좀 더 큰 단위의 작업이다. paging이 page 단위의 관리를 한다고 하면, swapping은 프로세스가 사용하는 모든 page를 관리한다. 그러므로 다시 그 프로세스가 돌아가기 위해서는 관련된 모든 page가 메모리로 읽혀져야 하ㄴ므로 성능에 막대한 지장이 있다.
시스템이 정상적으로 운영되기 위해서는 Swapping은 절대 발생하지 않아야 하며, Paging도 되도록 겹쳐 발생하지 않도록 해야 한다. 그러므로 메모리를 모니터링할 때는 주로 paging과 swapping의 유무와 양을 중점적으로 분석한다. Paging과 Swapping의 내역을 보려면 다음과 같은 명령을 사용하면 된다.

paging

# sar -p 3 5

SunOS 5.10 Generic_137111-01 sun4u    09/14/2012

14:43:48  atch/s  pgin/s ppgin/s  pflt/s  vflt/s slock/s
14:43:51   20.07    2.96    2.96    1.32   37.50    0.00
14:43:54   89.11    5.28    5.28  211.22  511.22    0.00
14:43:57  119.02    5.25   26.23  242.30 1349.84    0.00
14:44:00  142.76    7.24   29.28  302.96  705.92    0.00
14:44:03  284.21   17.11   85.86  767.76 1428.95    0.00

Average   131.05    7.57   29.93  305.13  807.24    0.00

swapping
# sar -w 3 5

SunOS 5.10 Generic_137111-01 sun4u    09/14/2012

14:44:06 swpin/s bswin/s swpot/s bswot/s pswch/s
14:44:09    0.00     0.0    0.00     0.0    5491
14:44:12    0.00     0.0    0.00     0.0    4849
14:44:15    0.00     0.0    0.00     0.0    2001
14:44:18    0.00     0.0    0.00     0.0    3976
14:44:21    0.00     0.0    0.00     0.0    2094

Average     0.00     0.0    0.00     0.0    3682

시스템 내에 paging, swapping이 많이 발생하면 시스템의 성능을 보장할 수 없다. 현재 사용 가능한 Physical 메모리 내에 대부분의 사용 메모리가 들어갈 수 있도록 시스템을 재구성해야 한다.
현재 1GB의 메모리가 있다고 가정할 때, 유닉스 커널이 사용하는 메모리, 오라클 데이터베이스의 SGA영역, 개별 프로세스가 점유하는 메모리의 합이 일반적으로 고려되는 메모리의 양이다. 오라클의 SGA영역은 OS의 전체 메모리 중 40~60%를 사용하도록 지정한다.
만약 OS에 Swapping, Paging이 많이 발생해 메모리가 부족하다고 판단될 경우에는 메모리의 사용량을 줄여 Swapping, Paging을 없애야 한다. 따라서 초기 설정값을 지정하고 메모리의 사용량∙Swapping∙Paging의 양을 보고 SGA를 좀더 늘리거나 줄이면서 최적화된 메모리 사용량 구조를 도출하면 된다.

I/O 튜닝

... 시간관계상 다음 기회에...

2012년 9월 13일 목요일

C#에서 FarPointSpread CheckBox 사용


FarPointSpread에서 CheckBox를 사용하기위해 아래와 같이 선언한다.

FarPoint.Win.Spread.CellType.CheckBoxCellType checkBoxCellType6 = new FarPoint.Win.Spread.CellType.CheckBoxCellType();

선언한 후 cell에 적용은 아래와 같이.
this.fpSpread1_Sheet1.Columns.Get(8).CellType = checkBoxCellType6;

 Spread의 각 Row의 CheckBox 상태를 확인하기 위해서 다음과 같이 처리했다.
if (_ActiveSheet.GetValue(i, COL_MSG_SEND_YN) != null && bool.Parse(_ActiveSheet.GetValue(i, COL_MSG_SEND_YN).ToString()))
CheckBox가 체크되었다면 true, 체크 되지 않았다면 false가 된다.

FarPointSpread ClearRange

Spread에 출력되어 있는 모든 데이터를 초기화 하기 위해 다음과 같이 처리했다.


private void btnInit_Click(object sender, EventArgs e)
{
    _ActiveSheet.ClearRange(0, 0, _ActiveSheet.Rows.Count, _ActiveSheet.Columns.Count, true);
    _ActiveSheet.Rows.Count = 0;
}
 ClearRange는 다음과 같이 정의되어 있다.


 //
// 요약:
 //     Removes all of the data, formatting, formulas, and notes from a range of
//     cells on this sheet.
//
// 매개 변수:
//   row:
//     Row index of first cell in range
//
//   column:
//     Column index of first cell in range
//
//   rowCount:
//     Number of rows in range
//
//   columnCount:
//     Number of columns in range
//
//   dataOnly:
//     Whether to remove only data
public void ClearRange(int row, int column, int rowCount, int columnCount, bool dataOnly);

 _ActiveSheet.Rows.Count = 0; 처리를 하지 않으면 데이터는 초기화 되지만 빈 Spread가 그대로 남아있다.



C#에서 버튼(button) 호출

제목이 좀 이상한듯한데-_-; UI에서 버튼을 눌러 호출되는 함수를 그냥 code 상에서 호출할 때 다음과 같이 처리했다.


private void btnInit_Click(object sender, EventArgs e)
{
    _ActiveSheet.ClearRange(0, 0, _ActiveSheet.Rows.Count, _ActiveSheet.Columns.Count, true);
    _ActiveSheet.Rows.Count = 0;
}

위와 같은 함수를 호출하려면

btnInit_Click(null, null); 

요렇게 한다.

너무 기초적인건가;

C#과 FarPointSpread를 이용하여 "HH:mm" 형식으로 시간출력

Spread 상에는 "HH:mm" 형식으로 출력되고 DB에는 char(4) - HHmm 형식으로 저장시키기 위해 다음과 같이 처리했다.


private DateTime SetCheckTime(string time)
{
    int hour = int.Parse(time.Substring(0, 2));
    int minute = int.Parse(time.Substring(2, 2));
    DateTime retv = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hour, minute, 0);
    return retv;
}

time은 "1234", "1212" 같은 문자열 이다.

Substring 을 이용하여 시와 분을 분리하고 int.Parse를 이용하여 각각 hour, minute 변수에 데이터를 넣는다.

그리고 DateTime 형식의 변수에 저장한다.



FarPointSpread에서는 다음과 같은 구현된다.

FarPoint.Win.Spread.CellType.DateTimeCellType dateTimeCellType6 = new FarPoint.Win.Spread.CellType.DateTimeCellType();
...

dateTimeCellType6.CalendarSurroundingDaysColor = System.Drawing.SystemColors.GrayText;
dateTimeCellType6.DateDefault = new System.DateTime(2012, 8, 30, 21, 58, 41, 0);
dateTimeCellType6.DateTimeFormat = FarPoint.Win.Spread.CellType.DateTimeFormat.UserDefined;
dateTimeCellType6.MaximumTime = System.TimeSpan.Parse("23:59:59.9999999");
dateTimeCellType6.TimeDefault = new System.DateTime(2012, 8, 30, 21, 58, 41, 0);
dateTimeCellType6.UserDefinedFormat = "HH:mm";
this.fpSpread1_Sheet1.Columns.Get(9).CellType = dateTimeCellType6;

CalendarSurroundingDaysColor, DateDefault  는 왜 포함되는지 잘 모르겠다;

나머지 코드는 차근차근보면 어떤 의미인지 알 듯하다.

이런식으로 처리해 놓고 해당 cell에 DateTime을 입력하면 "12:34", "12:12" 형식으로 출력된다.



Spread 상에 출력되어 있는 시간을 문자열로 받아들이기 위해 다음과 같이 처리했다.

data._checkTime = (((DateTime)_ActiveSheet.GetValue(i, COL_CHK_TIME)).Hour).ToString().PadLeft(2, '0') + (((DateTime)_ActiveSheet.GetValue(i, COL_CHK_TIME)).Minute).ToString().PadLeft(2, '0');

시간과 분을 나누어서 string으로 만들고 두 string을 붙인다.

각 string은 PadLeft 함수를 사용하여 "03", "05" 형식으로 만든다.



C#에서 Hashtable 사용

C#에 IBatis를 이용하여 프로그램을 개발 중이다.

query에 binding 처리를 하기 위해 parameterClass를 HashTable 형식으로xml에 매개변수를 전달한다.



private Hashtable ToParameter(ProcessCheckMaster obj)
{
    Hashtable param = new Hashtable();
    param.Add("CHK_ID", obj._checkID);
    param.Add("CHK_DIV", obj._checkDiv);
    param.Add("CHK_DETAIL_ID", obj._checkDetailID);
    param.Add("CHK_FILE_NO", obj._checkFileNo);
    param.Add("FILE_SEND_DIV", obj._fileSendDiv);
    param.Add("MESSAGE_SEND_YN", obj._msgSendYN);
    param.Add("CHK_TIME", obj._checkTime);
    param.Add("DATA_CNT", obj._dataCount);
    return param;
}

위의 함수는 Hashtable 형식으로 parameter를 만들기위해 사용한다.

2012년 9월 12일 수요일

C#에서 Panel 사용

여러개의 화면(Form)에서 공통의 사용자정의컨트롤을 사용할 경우 Panel을 이용하여 사용자정의컨트롤을 재사용할 수 있다.


private void frmSendFile_Load(object sender, EventArgs e)
{
    panel1.Controls.Clear();
    panel1.Controls.Add(new ctrlCheckUser());
}

위와 같이 사용하면  panel에 사용자정의컨트롤인 ctrlCheckUser이 출력된다.

C#에서 IList와 List

요즘 C#과 IBatis를 이용하여 프로그램을 개발하고 있다.

IBatis 사용이 익숙하지 않아 삽질의 연속이다.


public static IList<Hashtable> SelectQuery(string queryname, Hashtable parameter)
{
    string msg = string.Format(SELECT_QUERY, queryname);
    DataLog.WriteLog(_Logger, msg, parameter);
    return Mapper.Instance().QueryForList<Hashtable>(queryname, parameter);
}
위와 같이 SelectQuery() 함수를 만들어 이용하고 있는데, IBatis의 QueryForList() 함수는 IList<T>로 return한다.

IBatis의 QueryForList() 함수는 다음과 같이 정의되어 있다.
IList<T> QueryForList<T>(string statementName, object parameterObject);

아무든 IList<Hashtable>로 리턴 받은 값은 다음과 같이 사용할 수 있다.

private void btnSearch_Click(object sender, EventArgs e)
{
  IList<Hashtable> result = DBQuery.SelectQuery(SQL.SELECT_SEND_FILE_PROCESS_CHK_MASTER, GetSearchCondi());
  PrintSpreadProcessChkMaster(result);

private void PrintSpreadProcessChkMaster(IList<Hashtable> result)
{
    DefaultSheetDataModel model = new DefaultSheetDataModel();
    model.RowCount = result.Count;
    model.ColumnCount = COL_MAX;
 
    for (int i = 0; i < result.Count; i++)
    {
        model.SetValue(i, COL_ORG_ID, result[i]["HOLD_ORG_ID"].ToString());
        model.SetValue(i, COL_ORG_NAME, result[i]["HOLD_ORG_NAME"].ToString());
        model.SetValue(i, COL_FOLDER, result[i]["FOLDER"].ToString());
        model.SetValue(i, COL_FILE_NO, result[i]["FILE_NO"].ToString());
        model.SetValue(i, COL_FILE_NAME, result[i]["FILE_NM_FORMAT"].ToString());
        model.SetValue(i, COL_MAKE_PG, result[i]["MAKE_PG"].ToString());
        model.SetValue(i, COL_TRANS_TYPE, ConvertTransTypeToString(result[i]["TRANS_TYPE"].ToString()));
        model.SetValue(i, COL_MSG_SEND_YN, result[i]["MESSAGE_SEND_YN"].ToString() == "1" ? true : false);
        model.SetValue(i, COL_CHK_TIME, SetCheckTime(result[i]["CHK_TIME"].ToString()));
        model.SetValue(i, COL_CHK_ID, result[i]["CHK_ID"].ToString());
    }
    _ActiveSheet.Models.Data = model;
query에서 넘겨받은 값을 result[i]["HOLD_ORG_ID"].ToString() 과 같이 사용한다.



List<T>는 IList<T>와 조금 다르게 사용한다.


private void AddSendFileList(List<SendFile> list)
{
    DefaultSheetDataModel model = new DefaultSheetDataModel();
    model.RowCount = list.Count;
    model.ColumnCount = COL_MAX;
    for (int i = 0; i < list.Count; i++)
    {
        model.SetValue(i, COL_STATUS, "추가");
        model.SetValue(i, COL_ORG_ID, list[i]._holdOrgID);
        model.SetValue(i, COL_ORG_NAME, list[i]._holdOrgName);
        model.SetValue(i, COL_FOLDER, list[i]._folder);
        model.SetValue(i, COL_FILE_NO, list[i]._fileNo);
        model.SetValue(i, COL_FILE_NAME, list[i]._fileNameFormat);
        model.SetValue(i, COL_MAKE_PG, list[i]._makePG);
        model.SetValue(i, COL_TRANS_TYPE, ConvertTransTypeToString(list[i]._transType));
    }
    _ActiveSheet.Models.Data = model;
}

Hashtable도 참 생소하구나-_-;


C#에서 FarPoint Spread 출력

C#에서 FarPoint Spread 출력은 일단 두가지 방식이 있다.

일단 두가지 방식을 보자.

첫번째 방식이다.


int cnt = list.Count;
for (int i = _ActiveSheet.Rows.Count, j = 0; j < cnt; i++, j++)
{
    _ActiveSheet.AddRows(_ActiveSheet.Rows.Count, 1);
    _ActiveSheet.SetValue(i, COL_STATUS, "추가");
    _ActiveSheet.SetValue(i, COL_ORG_ID, list[j]._holdOrgID);
    _ActiveSheet.SetValue(i, COL_ORG_NAME, list[j]._holdOrgName);
    _ActiveSheet.SetValue(i, COL_FOLDER, list[j]._folder);
    _ActiveSheet.SetValue(i, COL_FILE_NO, list[j]._fileNo);
    _ActiveSheet.SetValue(i, COL_FILE_NAME, list[j]._fileNameFormat);
    _ActiveSheet.SetValue(i, COL_MAKE_PG, list[j]._makePG);
    _ActiveSheet.SetValue(i, COL_TRANS_TYPE, ConvertTransTypeToString(list[j]._transType));
}
AddRows를 사용하여 _ActiveSheet에 Row를 추가하고 각 Column에 직접 값을 기록한다.

이제 두번째 방식을 보자.


DefaultSheetDataModel model = new DefaultSheetDataModel();
model.RowCount = list.Count;
model.ColumnCount = COL_MAX;
for (int i = 0; i < list.Count; i++)
{
    model.SetValue(i, COL_STATUS, "추가");
    model.SetValue(i, COL_ORG_ID, list[i]._holdOrgID);
    model.SetValue(i, COL_ORG_NAME, list[i]._holdOrgName);
    model.SetValue(i, COL_FOLDER, list[i]._folder);
    model.SetValue(i, COL_FILE_NO, list[i]._fileNo);
    model.SetValue(i, COL_FILE_NAME, list[i]._fileNameFormat);
    model.SetValue(i, COL_MAKE_PG, list[i]._makePG);
    model.SetValue(i, COL_TRANS_TYPE, ConvertTransTypeToString(list[i]._transType));
}
_ActiveSheet.Models.Data = model;

http://tryinsights.blogspot.kr/2012/09/farpoint-spread-defaultsheetdatamodel.html 에서 설명한 것과 같이 DefaultSheetDataModel class를 이용한다.

테스트를 해보지 않아 어느 방식이 어떤 상황에서 더 효율적이다 라고 말하긴 어렵다.

하지만 후자 방식이 좀더 빠를 것 같은 느낌(?)이 든다.

그냥 느낌이다-_-;


FarPoint Spread의 DefaultSheetDataModel

FarPoint Spread에는 DefaultSheetDataModel 이라는 Class가 존재한다.

이 Class는 다음과 같이 사용할 수 있다.


private void PrintSpreadProcessChkMaster(IList<Hashtable> result)
{
    DefaultSheetDataModel model = new DefaultSheetDataModel();
    model.RowCount = result.Count;
    model.ColumnCount = COL_MAX;

    for (int i = 0; i < result.Count; i++)
    {
        model.SetValue(i, COL_ORG_ID, result[i]["HOLD_ORG_ID"].ToString());
        model.SetValue(i, COL_ORG_NAME, result[i]["HOLD_ORG_NAME"].ToString());
        model.SetValue(i, COL_FOLDER, result[i]["FOLDER"].ToString());
        model.SetValue(i, COL_FILE_NO, result[i]["FILE_NO"].ToString());
        model.SetValue(i, COL_FILE_NAME, result[i]["FILE_NM_FORMAT"].ToString());
        model.SetValue(i, COL_MAKE_PG, result[i]["MAKE_PG"].ToString());
        model.SetValue(i, COL_TRANS_TYPE, ConvertTransTypeToString(result[i]["TRANS_TYPE"].ToString()));
        model.SetValue(i, COL_MSG_SEND_YN, result[i]["MESSAGE_SEND_YN"].ToString() == "1" ? true : false);
        model.SetValue(i, COL_CHK_TIME, SetCheckTime(result[i]["CHK_TIME"].ToString()));
        model.SetValue(i, COL_CHK_ID, result[i]["CHK_ID"].ToString());
    }
    _ActiveSheet.Models.Data = model;
}

http://tryinsights.blogspot.kr/2012/08/c-farpoint-spread-activesheet.html 에서 설명한 것처럼 _ActiveSheet 변수를 설정한 후, 위와 같이 DefaultSheetDataModel class를 사용하여 Spread에 데이터를 출력한다.

C#에서 FarPoint Spread control

C#에서 FarPoint Spread  컨트롤 방법은 다음과 같다.

Column Header의 Label 변경

this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 1).Value = "상태";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 2).Value = "기관코드";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 3).Value = "기관명";


Column의 폭(width) 설정
this.fpSpread1_Sheet1.Columns.Get(0).Width = 48F;

Column의 값을 사용자가 수정하지 못하도록 설정
this.fpSpread1_Sheet1.Columns.Get(1).Locked = true; 

특정 Column에 속한 Cell Value의 정렬
this.fpSpread1_Sheet1.Columns.Get(6).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(7).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Left; 

Column Hidden 처리
this.fpSpread1_Sheet1.Columns.Get(9).Visible = false; 

Row Header Hidden 처리
_fpUserList.RowHeader.Visible = false; 

Column의 Size 변경 불가
_ActiveSheet.ColumnHeader.Columns.Default.Resizable = false; 
Column Header를 눌렀을때 Sorting
_fpHoldOrgList.Columns.Get(SP_HOLD_ORG_LIST_HOLD_ORG_ID, SP_HOLD_ORG_LIST_FOLDER).AllowAutoSort = true; 
CheckBox 사용
FarPoint.Win.Spread.CellType.CheckBoxCellType checkBoxCellType6 = new FarPoint.Win.Spread.CellType.CheckBoxCellType();

this.fpSpread1_Sheet1.Columns.Get(8).CellType = checkBoxCellType6; 

Oracle SQL Developer 훓어보기

Oracle SQL Developer를 설치했다.

Toad는 제대로 사용하지 못해봐서 잘 모르겠고, 주로 사용하는 Golden 보다는 성능이 좋은 것 같다.

성능이 낫다고 말하긴 애매하구나. 성능이라기보다는 편의성이 나은것 같다.

Oracle SQL Developer의 기능을 간략히 설명하자면...

Query Builder 가 있다.
MS의 Access를 생각나게하는 인터페이스를 가지고 있다.
일단 Drag & Drop이되고 sql로 select 하는 거의 모든 작업을 처리할 수 있을 듯 하다.
선책한 object의 이름을 변경할 수도 있고, 조회 결과를 sorting할 수도있다.

SQL Tuning Advisor 도 있는데 잘 사용하게 될지는 의문.

Exporting 기능을 앞으로 자중 사용하게 될 것 같다.
여러가지 조건을 넣어서 .sql 파일로 만들 수 있고, 데이터도 html, csv 등의 format으로 생성할 수 있는 듯하다.

Importing 기능은 시간상 생략.

Database Navigator 기능은 ADMIN 관련 기능인듯한다. Oracle 설정값 등을 확인할 수 있는데 내가 쓸일이 있을까?

DBMS Schedule는 MS-SQL의 DTS와 유사한 기능인듯하다.
잘쓰면 매우 유용할듯. 상당히 visual 하게 작업을 보여준다. 당연히 예약작업도 되고.

Explain Plan Diff.
이건 정말 많이 사용할 듯하다. Golden에서는 예상되는 plan을 보여주는 정도였는데, 여기서는 유사한 두개의 Plan을 비교할 수도 있다. 잘 써먹어봐야겠다.

시간이 부족해 이정도만 확인해봤는데, Reporting 기능도 있고, 11g에서만 사용되는 기능도 있는듯 하다.

현재 버전은 Oracle SQL Developer 3.2 (3.2.09.30)이고 위의 기능설명은 3.0 기준이다.

3.1과 3.2의 New Features 도 시간관계상 확인을 못했다.

이 글도 시리즈 물이 되려나...

linux cluster, oracle 관련 참고사이트

linux에 oracle을 설치하고 cluster를 구현할 수 있는 방법을 검색하다가 좋은 사이트를 발견했다.

시스템 엔지니어 공동 관리 구역 - http://blog.syszone.co.kr/

클루닉스에 재직중(? 아직도 재직중이신지는 모르겠다.)이신 서진우님이 운영하시는 blog 인 듯하다.

앞으로 회사 시스템이 Solaris에서 RedHet Linux로 전환될 가능성이 높아보이는데 이 사이트에서 얻을 수 있는 정보가 많이 보인다.

검색해서 발견했던 페이지는 요것. - 리눅스 클러스터 종합기술백서 http://blog.syszone.co.kr/2784

...

linux에 oracle을 설치하고 cluster를 구현할 수 있는 방법은 확인 못했다 -_-;

2012년 9월 11일 화요일

TPC - Transaction Processing Performance Council


1988년에 34개 소프트웨어 및 하드웨어 업체가 Transaction Processing Performance Council (TPC)을 공동으로 설립.

TPC에서 TPC-A, TPC-B 등의 벤치마크 방식을 제안.

현재 A, B 등은 사용되지 않고, 의미있다고 여겨지는 TPC 벤치마크는 TPC-App, TPC-C, TPC-E, TPC-H 등이다.

참고
TPS - Transaction Per Second의 약자로 초당 처리할 수 있는 트랜잭션의 수를 의미

관련링크
DBMS 벤치마크와 벤치마크 전쟁 - http://altistory.net/672



아래 내용은 레디시스템 홈페이지에서 발췌
http://www.readysystem.co.kr/ready/bbs/board.php?bo_table=tech_solaris&wr_id=147&page=4




TPC-C Overview

http://www.tpc.org

비교적 복잡한 OLTP 트랜잭션
TPC 조직이 2 년에 걸쳐 개발한 결과 전형적인 주문입력 시스템을 기본 구조로 설정하여 벤치마크를 위한 개념 설립
주문관리 도매상 어플리케이션을 모델로 설정
5개 유형의 트랜잭션으로 구성된 워크로드
처리량에 따른 사용자 및 Database의 증가
Full-Screen 사용자 인터페이스를 SPEC 정의
1분 당 신규 주문 처리 건수(tpmC) 및 가격 대비 성능($/tpmC)에 대한 값을 측정
1992년 7월 23일 TPC-C 테스트 승인
현재 Version 5 발표


  • TPC-C Workload

OLTP Transaction 유형 (80년대말~90년대초 표준)

New-order : 고객으로부터 새로운 주문 입력
Payment : 고객의 지불 처리 및 잔고 Update
Delivery : 주문 처리 (Batch 작업)
Order-status : 고객의 가장 최근 주문 상태 확인
Stock-level : 창고의 재고현황을 모니터링

한 개의 Database와 9개의 Table로 구성
Update, Insert, Delete 및 Abort Transaction으로 구성 (Primary or Secondary Key Index).
응답시간 요구사항 : 90% 이상의 Transaction이 5초 이하의 응답시간, Stock-level Transaction의 경우는 20초 이하



TPC-H Overview



  • TPC-H Benchmark (DW, BI)

의사 결정 시스템과 같은 Decision Support Benchmark Test
실제 비즈니스 상황을 반영한 대용량 Database에 대한 복잡한 22개의 Ad-hoc 쿼리 및 2개의 데이터 조작 문장으로 구성



  • TPC-H에 사용되는 쿼리문

실제 비즈니스 상황에서 필요로 하는 ad-hoc 쿼리문으로 구성
일반적인 OLTP 트랜젝션에 비해 훨씬 복잡함
광범위한 조작과 제약(Constraints) 포함
CPU 성능 외 Memory, I/O 등 데이터베이스 전반적인 부품에 대한 집중적인(intensive) 부하 발생
대용량의 데이터베이스에 대한 요구



  • TPC-H 단위

QphH@Size (TPC-H Composite Query per Hour)
Size는 Benchmark에 사용된 데이터베이스의 크기로 1GB, 10GB, 30GB, 100GB, 300GB, 1000GB, 3000GB, 10000GB의 몇 가지 지정된 크기를 명시함. 이 Database 크기는 Scale Factor(SF)로 TPC-H 산출 공식에서 사용
사용된 Database의 크기가 1GB 이면 SF=1, 3TB이면 SF=3000



  • TPC-H의 결과

TPC-H 값이 3000 QphH@300GB라면 이 수치의 의미는 300GB 용량의 Database에서 3000/300 = 10개의 Adhoc Query를 한시간에 수행할 수 있는 능력을 의미 (SF=300)
Database의 Size가 다른 QphH의 비교는 무의미하며 잘못된 결과를 초래할 수 있으므로 주의


참고 - SPEC : SPEC[스펙]은 여러 컴퓨터 및 마이크로프로세서 공급자들이 벤치마크 테스트의 표준을 만들기 위해 1988년에 설립한 비영리기관이다.


SPEC Overview


http://www.spec.org
Standard Performance Evaluation Corporation



  • SPECcpu2000

Processor, Memory, Compiler 등과 같은 Unit이 얼마나 뛰어난가 측정하는 표준
정수 및 실수 (부동 소수점) 에 대해 연산 위주의 작업을 수행하여 결과를 측정
SPECint: 하나의 정수연산을 얼마나 빠르게 수행하는가? Speed에 대한 측정
SPECfp: 하나의 실수연산을 얼마나 빠르게 수행하는가? Speed에 대한 측정
SPECint_rate: 주어진 시간동안에 얼마나 많은 정수연산 작업을 수행하는가? 대역폭에 대한 측정
SPECfp_rate: 주어진 시간동안에 얼마나 많은 실수연산 작업을 수행하는가? 대역폭에 대한 측정




  • SPECweb

SPECweb96: 정적 환경의 Web Server에 대한 성능 측정 (HTML, Image Downloading)
SPECweb99: 동적 환경의 Web Server에 대한 성능 측정 (DHTML, CGI etc)
SPECweb_SSL: SSL 기반의 암호화 기법이 적용된 Web Server에 대한 성능 측정



Oracle(또는 DB) 성능 측정 방법 1

제목에 1이란 숫자를 붙인건 이 주제와 관련된 글을 앞으로도 계속 쓸 것 같은 예감이 들었기 때문이다.

DB Migration, DB 교체 또는 신규 DB System 도입이라는 타이틀이 붙은 업무를 진행해야 하는데, 도대체 성능측정은 어떻게 해야 하는지 감을 잡을 수가 없다.

현재 성능이 어떠한지 확인이 되야 새로 도입하는 DB System은 어느 정도의 spec이 적당한지 판단이 될텐데 어떤 근거로, 어떤 방법으로 확인해야 하는걸까?

이러저러한 이유로 Oracle(또는 DB) 성능 측정 방법을 검색하다 보니 Hammerora라는 Open Source Oracle Load Test Tool 을 발견했다.

TPC-C, TPC-H 등 요즘 주로 사용하는 성능측정 방법을 구현해 놓은 tool 이라고 한다.

한번 사용해 볼까 싶기도 하고... 이걸 꼭 해야 하나 싶기도 하고... 심난한 요즘이다.

제목은 그럴싸하게 붙여 놓고 잡담밖에 없구나.

Hammerora에 국한되지 말고 Oracle의 성능을 측정할 수 있는 방법을 계속 확인하고 기록해보자.

2012년 9월 10일 월요일

Preforce Merge(P4Merge), KDiff3 + TortoiseSVN사용방법

Preforce Merge(P4Merge), KDiff3 + TortoiseSVN사용방법

http://a.tk.co.kr/607

다음 설치시 방황하지 않기 위해.

Solaris 기본 정보 확인

운영체제의 기본정보
uname -a

SunOS console 5.10 Generic_137111-01 sun4u sparc SUNW,Sun-Fire-V210

운영체제의 기본정보
uname -X


System = SunOS
Node = console
Release = 5.10
KernelID = Generic_137111-01
Machine = sun4u
BusType = <unknown>
Serial = <unknown>
Users = <unknown>
OEM# = 0
Origin# = 1
NumCPU = 1

전반적인 상태점검
prtdiag -v


CPU 정보

psrinfo -v
가상 프로세서 0개의 상태: 09/10/2012 21:28:39
  온라인(01/29/2012 13:05:06 이후).
  sparcv9 프로세서는 1002 MHz로 작동합니다.,
        sparcv9 부동점 프로세서가 있습니다.

psrinfo -pv

물리적 프로세서에 1 가상 프로세서 있음(0)
  UltraSPARC-IIIi (portid 0 impl 0x16 ver 0x24 clock 1002 MHz)


물리적 메모리 정보

prtconf | grep Memory
Memory size: 2048 Megabytes


가상 메모리 정보

swap -l
swapfile             dev  swaplo 블록   사용 가능
/dev/dsk/c1t0d0s1   32,1      16 8388096 8388096


swap -s
총: 913936k 바이트 할당 + 36416k 예약 = 950352k 사용, 4800120k 사용 가능



IP 설정 확인
ifconfig -a



Routing Table 확인
netstat -nr



DNS Client 설정 확인
cat /etc/nsswitch.conf

cat /etc/resolv.conf







WebDAV

WebDAV : 웹하드디스크를 구현할 수 있고, FTP를 통하지 않고 HTTP 프로토콜을 통해 웹상의 파일을 송수신, 수정, 삭제할수 있는 프로토콜.


1. WebDAV란 무엇인가?

WebDAV는 Web-based Distributed Authoring and Versioning (웹기반 분산형 저작 및 버전관리)의 약자로 웹을 통하여 웹서버에 파일을 관리(목록 조회, 수정, 삭제, 이동 등)할 수 있는 확장된 HTTP 프로토콜을 말한다.

WebDAV 특징

- 파일 락킹(file locking) 지원 : 여러 명이 동시 접근이 가능한 웹에서 overwrite하는 것을 막는다.
- XML을 사용하여 데이터를 교환 (물론 사용자는 XML을 몰라도 된다.)
- 설정은 간단하지만 효과는 만점
- 쉬운 접근 제어
- 웹하드디스크 구현 가능


사이냅소프트

SQL AntiPattenrs을 읽다가 역자 소개에 "사이냅소프트에 근무한다." 는 문구가 눈에 들어왔다.

사이냅 소프트.

어디선가 많이 들어본 회사다.

궁금해서 찾아봤다.

문서 필터링(MS-Office, 한글 등에서 text 추출), Web Office 등을 주로 개발하는 회사.

개발자의 하루, 재교육 소개, 조엘 테스트 등 인력채용 홈페이지도 꼼꼼하게 잘 만들어 놓은게 인상적이었다.


2012년 8월 30일 목요일

C# StringBuilder

정말 원시시대에서 살다가 왔는지 처음보는 것들, 모르는 것들이 너무 많다. ㅠㅠ
열심히 공부하자.

C#에 StringBuilder 라는 것이 있다.

StringBuilder sb = new StringBuilder();

이런식으로 선언하면 된다.

sb 자체는 하나의 object로 인식되는 듯 하다.

sb.Append(list[i]._holdOrgName);
sb.Append(";"); 

이렇게 사용하면 각 변수의 항목이 sb에 순서대로 붙는다.

strcat 같은 함수를 더 편하게  사용하는 느낌이다.


txtOrg 라는 TextBox에 문자열을 출력하기 위해 다음과 같이 사용할 수 있다.
private System.Windows.Forms.TextBox txtOrg;
...
txtOrg.Text = sb.ToString();    // 화면에 출력

신기한 C# -_-;

string 형식으로도 충분히 구현가능 할텐데 왜 StringBuilder를 만들었을까?

단순히 편의성을 위해?

StringBuilder에 대해 좀 더 확인해봐야겠다.

추가
MSDN에서 확인해봤다.
http://msdn.microsoft.com/ko-kr/library/system.text.stringbuilder.aspx
단순한 문자객체가 아니라 class 였구나.
쓸만한 멤버 변수도 많아 보인다.
음... 속도는 어떨까?
속도도 한번 더 확인해보자.

C#에서 FarPoint Spread ActiveSheet

C#에서 FarPoint Spread를 사용할 때

public partial class frmSendFile : Form, IKisSmsForm
{
    private SheetView _ActiveSheet;
    ...
    
    public frmSendFile()
    {
        InitializeComponent();
        _ActiveSheet = fpSpread1.ActiveSheet;
    }
    ...
}
이렇게 선언해 놓으면 _ActiveSheet 변수를 사용하여 Spread를 컨트롤 할 수 있다.

예를 들어


_ActiveSheet.AddRows(_ActiveSheet.Rows.Count, 1);
_ActiveSheet.SetValue(i, COL_STATUS, ConvertStatusString(ADD));
요렇게 사용한다던가

int cnt = _ActiveSheet.Rows.Count;

_ActiveSheet.ColumnCount = COL_MAX;

이런식으로 사용할 수 있다.