2013년 12월 12일 목요일

Automatic Workload Repository (AWR)

오라클은 성능 분석에 대한 툴을 끊임없이 제공해왔다. 전통적으로는 UTLBSTAT/UTLESTAT 스크립트를 제공했고, 8i 버전에서는 Statspack을 소개하고 9i 버전에서는 해당 기능을 확장하였다. 그리고, 10g 에 이를 발전 시킨 기능이 Automatic Workload Repository (AWR) 이다.



AWR 정보

AWR에는 성능에 관계 된 다음과 같은 정보들이 포함된다.

  • 성능 문제를 분석하기 위한 대기 이벤트 정보
  • V$SESS_TIME_MODEL, V$SYS_TIME_MODEL 뷰를 통한 시간 기반의 통계 정보
  • V$ACTIVE_SEESION_HISTORY에서의 ACTIVE SESSION HISTORY (ASH) 정보
  • 시스템과 세션의 V$SYSSTAT과 V$SESSTAT 뷰를 통한 성능 정보
  • 오브젝트 사용통계
  • SQL 구문에 대한 자원 사용 정보


Snapshots

스냅샷은 기본적으로 매 시간 마다 수행되고, 통상 8일간 보관되게 된다. 이는 DBMS_WORKLOAD_REPOSITORY 패키지의 modify_snapshot_setting을 통해 변경이 가능하다.

DBMS_WORKLOAD_REPOSITORY 패키지를 활용하여 추가적인 스냅샷을 생성하는 것과 기존의 스냅샷을 삭제하는 것도 가능하다. (create_snapshot, drop_snapshot_range를 이용)



Baselines

베이스라인은 일정 시간 동안의 스냅샷을 종합하여 말 그대로 기준선을 만드는 것이다. 베이스라인이 생성되게 되면, 이 베이스라인을 기준으로 하여 특정 시점의 성능에 대해 비교하는 분석이 가능하다.



Workload Repository Views

AWR에 활용되는 뷰들은 다음과 같다.

  • V$ACTIVE_SESSION_HISTORY - Displays the active session history (ASH) sampled every second.
  • V$METRIC - Displays metric information.
  • V$METRICNAME - Displays the metrics associated with each metric group.
  • V$METRIC_HISTORY - Displays historical metrics.
  • V$METRICGROUP - Displays all metrics groups.
  • DBA_HIST_ACTIVE_SESS_HISTORY - Displays the history contents of the active session history.
  • DBA_HIST_BASELINE - Displays baseline information.
  • DBA_HIST_DATABASE_INSTANCE - Displays database environment information.
  • DBA_HIST_SNAPSHOT - Displays snapshot information.
  • DBA_HIST_SQL_PLAN - Displays SQL execution plans.
  • DBA_HIST_WR_CONTROL - Displays AWR settings.




Workload Repository Reports

다음 스크립트를 활용하여 리포트를 생성하는 것이 가능하다.
@$ORACLE_HOME/rdbms/admin/awrrpt.sql
@$ORACLE_HOME/rdbms/admin/awrrpti.sql



Active Session History (ASH)


기존 오라클에서 제공하던 성능 분석 관련한 툴들로는 Statspack, AWR, ADDM, SQL Trace 등을 꼽을 수 있다. 이들은 성능 튜닝이나 SQL 튜닝 등에 아주 잘 활용되었다고 말할 수 있다. 그러나, 이들의 단점은 이미 지난 이벤트에 대해 초점을 맞추고 있다는 것이다.

다시 말해, [G]V$ 뷰 등의 다이나믹 뷰에서 현재 일어나고 있는 이벤트에 대한 정보들에 집중하고자 하는 수요에 대해서는 기존의 툴들이 부족한 부분들이 존재했으며, 따라서 historical 한 정보들이 아닌 실시간에 가까운 정보를 제공하고자 하여 나온 것이 Active Session History (ASH) 이다.

오라클 10g 버전에서 이를 출시하면서, ASH를 Diagnostics and Tuning Pack에 포함시켰다. 즉, ASH의 사용을 위해서는 EE 라이선스가 필요하다.



V$ACTIVE_SESSION_HISTORY

해당 뷰는 매 초마다 대기 이벤트에 대한 정보를 수집한다. 여기서 Active Session 이란 샘플링 시점에 CPU 자원 사용을 위해 기다리거나 Idle 한 대기 클래스 상태이 있지 않은 세션을 의미한다. 샘플에 대한 정보는 SGA 내에 원형 구조의 정보로 쓰여지게 된다.

V$ACTIVE_SESSION_HISTORY 뷰 자체는 객관적인 정보만을 보관하는 테이블이다. 이는 다른 여러 정보들과 연결되어 종합적인 통계 정보를 제공한다. (SQL 구문, 실행 계획, 오브젝트, 대기 이벤트, 세션, 모듈, 액션, 서비스 명 등) 따라서, Active Session 의 작업 중인 내용이나 작업한 내용에 대해 유기적인 분석이 가능하다.

가령, 다음 쿼리는 5분 동안 일어난 데이터베이스의 작업에 대한 분석을 ASH를 통하여 한 것이다.

SELECT NVL(a.event, 'ON CPU') AS event,
       COUNT(*) AS total_wait_time
FROM   v$active_session_history a
WHERE  a.sample_time > SYSDATE - 5/(24*60) -- 5 mins
GROUP BY a.event
ORDER BY total_wait_time DESC;

EVENT                                               TOTAL_WAIT_TIME
--------------------------------------------------- ---------------
db file sequential read                                         750
log file parallel write                                          43
log file sync                                                    42
db file parallel read                                            32
control file sequential read                                     22
ON CPU                                                           21
db file parallel write                                           21
log file switch (private strand flush incomplete)                 8
Disk file operations I/O                                          1
control file parallel write                                       1
buffer busy waits                                                 1

11 rows selected.

주의할 점은, 이는 매 초마다 기록한 것을 일정 시간 마다 '샘플링 한 것'으로 (통상 10초 당 한 개의 샘플을 가져옴) TOTAL_WAIT_TIME 컬럼의 값을 이용하여 분석을 수행하지 WAIT_TIME 혹은 TIME_WAITED 컬럼을 이용하지는 않는다는 것이다. (즉, 산술 평균 값은 ASH 정보에서는 무의미 하다고 말할 수 있다.)

물론, ASH를 이용한 통계 정보 수집은 분명 놓치게 되는 정보들이 존재할 수 있음을 부정하지는 않는다. 그러나 분명한 사실은, 긴 대기 시간을 유발하는 SQL 구문이나 작업을 찾아내는 데에는 이러한 샘플링 방식이 훨씬 더 효율적이라는 것을 기억해야 한다. ASH 통계 정보가 작은 정보는 놓칠 수 있는 대신에 주요한 정보들은 놓칠 가능성이 거의 없다. (여기서 오는 한계점들은 다른 통계 정보를 활용할 수 있다.)



DBA_HIST_ACTIVE_SESS_HISTORY

이전에 수집된 ASH 데이터에 대해 접근하기 위해서는 DBA_HIST_ACTIVE_SESS_HISTORY 뷰를 이용하면 된다. 이는 샘플에 대한 샘플이라고 말할 수 있다. 이 뷰에 대한 사용법은 V$ACTIVE_SESSION_HISTORY와 비슷하지만, 10초 마다 샘플링 한 것에 대한 샘플임을 기억해야된다. (따라서, 평균적으로는 통계 정보의 카운트에 * 10을 해주는 것이 근접하게 해석할 수 있다.)

SELECT NVL(a.event, 'ON CPU') AS event,
       COUNT(*)*10 AS total_wait_time
FROM   dba_hist_active_sess_history a
WHERE  a.sample_time > SYSDATE - 1 
GROUP BY a.event
ORDER BY total_wait_time DESC;

EVENT                                            TOTAL_WAIT_TIME
------------------------------------------------ ---------------
db file sequential read                                     3860
ON CPU                                                      1500
control file sequential read                                 990
direct path read temp                                        580
direct path read                                             560
log file parallel write                                      280
db file parallel write                                       270
Disk file operations I/O                                     240
log file switch completion                                   150
log file sync                                                130
db file parallel read                                        130
.
.
.

26 rows selected.




Enterprise Manager (EM) 12c 에서 ASH 활용하기

데이터베이스 정보에서 Performace -> ASH Information 에서 해당 정보를 활용할 수 있다.




ASH Report 생성

 EM에서는 비교적 손쉽게 생성할 수 있고, SQL Plus에서도 다음 스크립트를 이용하여 해당작업을 수행할 수 있다.

$ORACLE_HOME/rdbms/admin/ashrpt.sql

2013년 12월 9일 월요일

SHA-2 Algorithm Source Code in Java

/*
Information in Wikipedia
http://en.wikipedia.org/wiki/SHA-2
*/

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA {

    private static char[] map1 = new char[64];
    static {
int i = 0;
for (char c = 'A'; c <= 'Z'; c++)
   map1[i++] = c;
for (char c = 'a'; c <= 'z'; c++)
   map1[i++] = c;
for (char c = '0'; c <= '9'; c++)
   map1[i++] = c;
map1[i++] = '+';
map1[i++] = '/';
    }

    public SHA() {
    }

    public static String encodeBASE64(byte[] in, int iLen) {

int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
int oLen = ((iLen + 2) / 3) * 4; // output length including padding
char[] out = new char[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
   int i0 = in[ip++] & 0xff;
   int i1 = ip < iLen ? in[ip++] & 0xff : 0;
   int i2 = ip < iLen ? in[ip++] & 0xff : 0;
   int o0 = i0 >>> 2;
   int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
   int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
   int o3 = i2 & 0x3F;
   out[op++] = map1[o0];
   out[op++] = map1[o1];
   out[op] = op < oDataLen ? map1[o2] : '=';
   op++;
   out[op] = op < oDataLen ? map1[o3] : '=';
   op++;
}
//System.out.println("Char Len = " + out.length);
return new String(out);
    }

    public static String encodeSHA256(String src) {
MessageDigest md = null;

try {
   md = MessageDigest.getInstance("SHA-256");
   byte[] input = src.getBytes();
   int len = input.length;
   md.update(input, 0, len);
   byte[] raw = md.digest();
   //System.out.println("Byte out =" + new String(raw));
   //System.out.println("Byte Len = " + raw.length);
   return encodeBASE64(raw,raw.length);
} catch (NoSuchAlgorithmException noalgo) {
   noalgo.printStackTrace();
}

return null;
    }

    public static void main(String[] argv) {
System.out.println( SHA.encodeSHA256("hello"));
System.out.println( SHA.encodeSHA256("jljdsljdglfglkdhfkgjhkjhdkgjhgkjhjhfdkhgdkjfhgk"));
    }
}