레이블이 ORACLE CASE인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ORACLE CASE인 게시물을 표시합니다. 모든 게시물 표시

2013년 8월 23일 금요일

오라클자바 Community에서 설립한 실무개발교육6년차 오엔제이 프로그래밍 실무교육센터 소개

1998년부터 운영된 오라클자바커뮤니티(www.oraclejavanew.kr)에서 설립 운영되고 있는 오엔제이 프로그래밍실무학원(www.onjprogramming.co.kr )은 개발자를 위한 SKILL UP, 실무개발교육 6년차 교육센터 입니다.

(2008년5월부터 오엔제이시스템즈에서 운영하던 "오라클자바교육센터"는 2013년5월 양도 하였으며 새로운 오엔제이 프로그래밍 실무교육센터에서 개발자 실무 교육을 이어갈 수 있도록 더욱 더 노력 하겠습니다.)

자바, 오라클의 기초부터 자바프레임워크(Struts, Spring), 오라클 튜닝, 모델링, 고급SQL, Xinternet(GAUCE, Miplatform, XPlatform), 닷넷(C#, ASP.Net), 스마트폰앱개발교육(안드로이드, 아이폰)까지 실무전문 교육을 진행하고 있습니다.
(본원은 TOBESOFT에서 공인 교육기관 입니다.)

자바, 스프링, 오라클 교육 받으셨는데 이론으로 교육을 받으셨다고요? IT프로그래밍 교육은 실전예제, 실습을 통해 이론을 습득을 해야 합니다. 본원은 모든 강좌가 실습을 통해 이론을 취득하는 실무중심 교육 입니다.

한번 방문 하시어 실무전문 교육의 진수를 느껴 보시기 바랍니다.

감사합니다.

2013년 8월 8일 목요일

[자바교육,오라클자바커뮤니티]Log4J를 XML을 이용하여 설정하기

Log4J를 XML을 이용하여 설정하기 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  
 
------------------------------------------------------------
1. log4j.configuration 파이를 /WEB-INF/classes 에 만듭니다.
------------------------------------------------------------

set CATALINA_OPTS=-Dlog4j.configuration=log4j.xml

------------------------------------------------------------
2. log4j.xml을 /WEB-INF/classes 에 만듭니다
------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>

<appender name="rolling" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="d:\myoutput.log"/>
        <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="=%d{ABSOLUTE} - %p %c - %m%n"/>
        </layout>
</appender>

<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%5p [%t] (%F:%L)- %m%n"/>
        </layout>
</appender>
<root>
<priority value ="INFO" />
<appender-ref ref="stdout" />
<appender-ref ref="rolling" />
</root>
</log4j:configuration>


------------------------------------------------------------
3. test용 JSP를 만듭니다.
------------------------------------------------------------

<%@ page import="org.apache.commons.logging.Log" %>
<%@ page import="org.apache.commons.logging.LogFactory" %>
<%-- Get a reference to the logger for this class --%>
<% Log logger = LogFactory.getLog( this.getClass( ) ); %>
<% logger.debug( "This is a debug message from a jsp" ); %>
<html>
<head>
<title>Using Commons Logging in a JSP page</title>
</head>
<body>
<% logger.info( "This is another log message in the jsp" );
%>
There should be two log messages in the log file.
</body>
</html>

콘솔 화면으로 로그가 출력 되면서 화일로도 출력이 되는 예제 입니다. 

2013년 8월 5일 월요일

(오라클시퀀스, ORACLEJAVA,오라클자바교육)Oracle Sequence

오라클 시퀀스는 DB Table의 자동증분 컬럼에 사용하면 유용하다. 아래 내용을 확인하자.



오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 



A. 개념
- Sequence는 순차적인 일련번호를 생성한다.(최대 38자리의 Oracle정수)
- Sequence는 다중 사용자환경에서 디스크 입출력 오버헤드나 Transaction Locking없이
고유한 순번을 생성하는데 용이하다.
- Sequence생성시 Sequence이름, 오름차순또는 내린차순여부, 번호간격등을 정의한다.
- Sequence번호는 Table과 독립적으로 생성되며,따라서 동일한 Sequence를 하나또는 여러
개의 Table에 사용할수 있다.
B. Sequence생성
- create sequence emp_sequence
increment by 1
start with 1
nomaxvalue
nocycle
cache 10;

cache Optiom은 일련의 Sequence를 미리 할당하고 메모리에 유지하면서 시퀀스를 빠르게 Access
할수있게 한다. 일련의 Sequence를 Cache하면 Sequence를 건너 뛸수있다.
예를들어 Instance가 비정상적으로 종료되면 캐시되었지만 사용안된 Sequence를 잃어버리게 된다.
즉 Cache를 상요하면 Sequence를 빠르게 Access할수 있으나 비정상적으로 종료돨 경우에는 번호가
건너 뛰게된다.

C. Sequence 변경
Alter sequence emp_sequence
Increment by 10
Maxvalue 10000
Cycle
Cache 20;
D. Sequence에 영향을 주는 변수
Sequence_cache_entries매개변수는 캐시될 시퀀스를 설정하다. 너무 낮으면 시퀀스값을 건너
뛸수도 있다. 예를들면 다섯개의 Cache된 Sequence를 사용하고 캐시가 다찼으며,매개변수 값이
4라면 현재 4개의 시퀀스가 Cache되었다면 캐시에서 최근에 가장적게 사용한 Sequence는 5번째
Sequence로 바뀌면서 이 Sequence의 모든 다른값(캐시된 마지막 Sequence까지)은 손실된다.

E. Sequence삭제
- drop sequence emp_sequence; 

(자바 스윙, 자바오라클교육,ORACLE)JAVA SWING JFC

JFC(Java Foundation Class)


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 


 www.onjprogramming.co.kr 


그래픽 사용자 인터페이스의 구현을 위한 일련의 기능요소를 묶은것으로 다음과 같은 요소가 포함 됩니다.
- 스윙컴포넌트(Swing Component)
- 교체 가능한 외양(Pluggable look & feel) 지원 GUI의 겉모습과 작동방식을 자유롭게 선택 교체할수 있게함 , 예를들면 같은 프로그램을 java look&feel로 또는 window look&feel로 나타내도록 할 수 있습니다.
- 접근지원 API 화면의 내용을 음성으로 읽어 주거나 점자로 출력하는등의 장애자용 인터페이스에 관련된 기능
- Java 2D API 고품질의 2D 그래픽, 텍스트, 이미지를 Appication이나 Applet등에서 쉽게 사용가능 - 드래그&드롭 지원 자바 어플리케이션과 운영체제 고유의 어플리케이션 사이에서 끌어놓기를 지원 합니다.



자바 스윙(Swing) 이란...
자바나 C++, C#등 보게 되면 처음에는 Helloworld 부터 컨솔화면에 찍기 시작하여 나중에는 멋진 윈도우 화면에 무언가 다이나믹한것을 만들게 됩니다. 어느정도 console 창(도스 창)에서 작성하는 프로그래밍에 숙련되면, GUI(graphic user interface)를 통해 작동하는 프로그램을 짜게 된다는 거죠~ 기본적으로 자바는 AWT(abstract window toolkit)라는 것을 제공하여 윈도우 프로그램을 개발 하게 했지만 무거우며 플랫폼나자 다른 형태로 나타나는 등의 단점이 있어 아마도 JDK1.2 이상에서 Swing이라는 것을 지원하기 시작 했습니다. 자바 프로그램에서 Swing을 이용하여 윈도우 프로그램을 개발할려면 import javax.swing.*; 형태로 사용 합니다. 또한 스윙 컴포넌트는 앞에 'J'를 붙입니다. 즉 기존 AWT에서 제공 되었던 컴포넌트와 구분하기 위해서 입니다.

스윙 Component와 AWT Component의 차이점
- 스윙 컴포넌트는 ‘ J ' 로 시작한다.(Button, JButtion)
- AWT컴포넌트는 java.awt 패키지안에, Swing 컴포넌트는 javax.swing 패키지 내에 존재 합니다.
- 모든 스윙 컴포넌트는 javax.swing.Jcomponent를 상속 합니다.
- 스윙 컴포넌트는 특정 플랫폼에 의존적인 코드가 전혀 포함되지 않고 구현됨 즉, 그들이 수행될 때 플랫폼으 로부터 어떠한 native code도 가져다 쓰지 않습니다.
- 스윙의 버튼은 텍스트뿐만 아니라 이미지도 표시 할 수 있습니다.
- 스윙 컴포넌트는 직사각형 이외의 모양도 가능 합니다.(둥근버튼)
- 프로그램 내에서 스윙컴포넌트와 중량(heavy weight) 컴포넌트를 사용하면 안된다. 즉시 사용가능한 AWT 컴포넌트나 AWT Canvas, Panel을 상속한 클래스는 중량컴포넌트이다. 경량과 중량이 곁쳐지는 경우에는 경량컴포넌트가 가려지기 때문이다.
- JFrame와 같은 최상위 컨테이너에 직접 컴포넌트를 추가하지 않습니다. 그대신 Jframe에 포함된 다른 컨테이너에 컴포넌트를 추가 하는 겁니다.(Panel등)
- 스윙에서는 Border를 그맇수 있습니다. AWT는 Peer를 거치므로 모양에 관여할수 없었지만, 스윙은 직접 그리 는것을 담당하므로 Border를 쉽게 그릴수 있습니다.
- 컴포넌트의 최대/최소 크기와 가장 적절한 크기를 지정 할 수 있습니다. AWT에서는 Peer에 의해 제어되므로 마 음대로 크기를 제어하기가 어렵습니다
- ToolTip을 만들기가 쉽습니다.(Jcomponent에 ToolTip에 대한 메소드가 존재)
- 투명한 Component가 가능(setOpaque() 이용하여 설정가능)
- Jframe은 윈도우 이벤트 핸들링을 하지 않아도 윈도우를 종료할수가 있다. 이는 내부적으로 이벤트 핸들링 코드가 존재하기 때문인데 프로그래머가 바꿀수 있도록 설정이 가능합니다. setDefaultCloseOperation(int) 이 라는 메소드를 이용 합니다. 파마미터로 java.swing.WindowConstants의 DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE,DISPOSE_ON_CLOSE 값을 이용할수 있으며 DISPOSE_ON_CLOSE가 기본값 입니다.

스윙의 특징
- 교체 가능한 외관(look & feel) --> look & feel이 동작도중에 동적으로 교체가 가능 합니다.. 자바의 확실한 멀티플랫폼 지원의 일부 현재 Window, java, Motif 세가지 외관이 지원 됩니다.
- MVC(Model View Controller) 모델 --> MVC 구조는 Alan Kay라는 사람이 만든 객체 지향 언어인 Smalltalk-80 version에서 소개 컴포넌트 디자인 모델의 하나로 각각의 컴포넌트를 Model, View, Controler로 구분하여 추상화 한것이며 ① 모델(Model) : 프로그램의 상태에 대한 논리적인 데이터를 표현, 또한 모델의 데이터가 변경되었을 경우 이를 뷰 객체에게 알려주는 역할을 하는 객체 입니다. ② 뷰(View) : 모델에 의해서 표현된 데이터에 대한 시각적인 화면 출력을 관리하는 객체 입니다. 뷰는 응답 메커니즘을 기술하기 위하여 콘트롤러를 이용 하는거죠 즉, 콘트롤러의 입력에 응답하여 그 결과를 화면으로 출력해 주는ㄴ것 입니다. ③ 콘트롤러(Controller) : 모델에 의해서 표현된 데이터를 사용자가 변경할 수 있도록 사용자 상호작용(User Interaction)을 제공하는 객체 입니다. JFC의 Swing에서의 MVC의 구조는 상태부분(Model)과 표현부분(View+Controller=UI)으로 구분함으로써 다음과 같은 특징을 갖는것 입니다.
- 같은 모델을 가지고 쉽게 동시에 여러 개의 뷰를 만들 수 있습니다.
- 모델에는 표현부분이 없기 때문에 모델의 영향을 주지 않고 필요에 따라 뷰를 자유롭게 수정할 수 있습니다.
- Swing 일반적인 MVC 구조에서 공통적으로 약간 변형시킨 형태로 컴포넌트를 표현 합니다. 즉, 뷰와 콘 트롤러를 하나로 묶어서 델리게이트라는 커다란 컴포넌트를 형성,모델은 바꾸지 않고 프로그램 실행 중 간에 Delegate(view+Controller)를 통해 Java Look&feel을 윈도우 look&feel로 바꿀 수가 있는 것입니다.
- 경량 컴포넌트(lightweight Component) : 시스템의 Native Component와 연계되지않은 컴포넌트, 반대로 AWT의 모든 컴포넌트는 Peer라는것을 통하여 시스템의 Native Component와 연계되어 있습니다. Native Component를 사용하지 않으므로 자원을 적게 소모하며 플랫폼에 독립적인 컴포넌트를 만들수 있는 것 입니다. 스윙 컴포넌트는 경량 컴포넌트라 말할 수 있습니다. 그렇다고 스윙 컴포넌트가 모두 경량 컴포넌 트라는 말은 아닙니다. 경량 컴포넌트는 완전히 Java 만으로 작성되어야 하고, 사용자가 임의로 룩앤필 을 바꿀 수 있는 것이라야 합니다 .
- 중량 컴포넌트란 그 플랫폼이 제공하는 컴포넌트로 사용자가 변화를 모색할 수 없는 매우 경직된 컴포넌트, AWT 컴포넌트는 중량형 컴포넌트 입니다.
- 스윙은 모든 플랫폼에서 동일한 외형을 갖고, 동일한 작동을 하며, 최대한 유연성을 갖는 완전히 Java 만으로 작성된 "경량형lightweight" 컴포넌트를 제공한다는 목적으로 시작된것 입니다.
아래는 간단한 스윙 예제 입니다.
[예제]
// HelloSwing.java
// JMEnuBar를 제외하고 나머지(JButton, LayoutManger등)을 JFrame에 추가할때 contentPane에 추가
// JFrame의 경우 윈도우 이벤트를 처리하지 않아도 윈도우는 종료되지만 프로그램이 종료되지는 않는다.
import java.awt.*; import java.awt.event.*; import javax.swing.*;
class HelloSwing extends JFrame {
public HelloSwing(String title) {
super(title);
display();
}
public void display() {
Container cpane;
JMenuBar mb = new JMenuBar();
JMenu menu;
menu = new JMenu("File");
menu.add(new JMenuItem("Open"));
menu.add(new JMenuItem("Save"));

menu.addSeparator();
menu.add(new JMenuItem("Exit"));
mb.add(menu);
setJMenuBar(mb);
cpane = getContentPane();
cpane.setLayout(new BorderLayout());
cpane.add(new JButton("안녕, 스윙"),BorderLayout.CENTER);
}
public static void main(String[] args) {
HelloSwing hs = new HelloSwing("수윙 시작... 시작이 반이다.");
hs.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
}
);
hs.pack(); hs.setSize(300, 200); hs.setVisible(true);
}
}




2013년 8월 4일 일요일

(오라클테이블)Oracle Table...

a. Oracle에서 Table은 Data저장 영역의 기본단위이다.
b. 선택적으로 Table의 각 Column에 규칙을 정할수 있는데 이를 Constraints(무결성제약조건)
이라고 한다.한예로 Not Null은 무결성제약조건 입니다.
c. Cluster화되지 않은 Table을 작성할때 Oracle은 Table의 향후 Data를 보관하기위해
TableSpace에 Data Segment를 자동으로 할당한다.
Data Segment에 대한 저장영역 매개변수를 설정하여 (initial, next parameter등) Data
Segment에 대한 할당된영역(extents)을 제어할수 있다.
Data Segment에 대해 pctfree와 pctused를 이용하여 Data Block의 빈영역에 대해 제어할
수도 있다.
d. 전체행을 단일 Data Block에 Insert할수 있다면 Oracle은 행을 하나의 행조각으로 저장하
나 전체행을 단일 Data Block에 Insert할수 없다면 기존 행을 갱신하여 행이 Data Block의 크기를
증가시키는 경우(Update된 Record가 이전의 Record보다 Size가 커지는 경우) Oracle은 여러 개의
행조각을 사용하여 Data를 저장한다. Oracle이 하나의 행을 두개이상의 행조각으로 저장하는 경우
Block을 통해 Chain화 되며, 체인화된 행조각은 부분의 RowID를 이용하여 서로 체인화 된다. 또한
체인화에 관계없이 각각의 행조각은 행/열 전체또는 일부에 대한 행 헤더 및 Data를 포함한다.

e. 행 헤더는 행조각,(체인화된 행조각의 경우)체인화, 행조각의 열,(Cluster인경우)클러스터
키등을 포함한다.
하나의 Block에 완전히 포함된 Cluster화 되지않은 행에는 적어도 3 Byte의 행헤더가 있으며,
행헤더 정보 다음에 열길이와 Data가 포함된다. 열 길이는 250 Byte이하를 저장하는 열의 경우
1 Byte,그이상인경우 3 Byte가 필요하며 열 Data에 선행한다.
열 Data에 필요한 영역은 Data Type에 따라 틀리며, 가변길이인 경우엔 영역은 증가또는 감소할수
있다.영역을 보존하기 위해 Null은 열길이(0)만을 저장한다. Oracle은 Null Column에 대한
Data를 저장하지 않으며 후행하는 Null의 경우 행헤더가 새로운 행의 시작을 나타내므로 열길이를
저장하지 않는다.(예를들어 Table의 마지막세개의 Column이 Null인 경우 열에 정보를 저장하지
않는다.)
또한 각각의 행은 Data Block헤더의 행 Directory에 2 Byte를 사용한다.

f. Column순서는 Table의 모든 행에 대해 동일 하다.일반적으로 열은 Create Table명령문에
나열된 순서대로 저장되지만 꼭 그렇지는 않다. 예를들어 Long Data Type의 Column이 
있는 Table을 Create하는 경우 항상 이 Column을 마지막으로 저장한다. 또한 alter table
등의 명령으로 Column을 Add하는 경우 새로운 Column을 마지막에 추가한다.
일반적으로 행이 적은 영역을 차지하도록 Null을 자주 포함하는 Column을 마지막에 두
는 것이 좋다 만약 Table이 Long Column을 포함하면 Long Column이 마지막에 위치 하
므로 이러한 이점을 살리기 힘들다.
g. ROWID는 각각의 행조각을 위치나 주소로 식별한다. 일단 행조각에 ROWID를 부여 하
면 행조각은 IMPORT 및 EXPORT Utility를 사용하여 행을 삭제할 때까지 ROWID를 보유 합니다.
행의 Cluster Key값이 변경되면 행은 유일한 ROWID를 유지하면서 새로운 값에 대한 추가
포인터 ROWID를 얻는다.

h. Null은 행의 열에 값이 없음을 나타내는데 Data값을 가진 열사이에 위치하는 경우 Null
 은 열길이(0)을 저장하는데 1 Byte가 필요함

[Table생성 예제]
create table test
(
 id  char(3)      not null,
 name varchar2(12)    null,
 addr varchar2(50)    null,
 constraint pk_test (id) primary key
 using index
 pctfree 10
 pctused 60
 storage
 (initial 100k next 100k)
 tablespace users_idx
)
storage
(initial 200k
next    200k
minextents 1
maxextents 121
pctincrease 0)
tablespace users;

2013년 8월 3일 토요일

Oracle SQL Execution Explain Plan실행계획 SQL 연산(FILTER)

SQL 연산(FILTER)

구로디지털 오엔제이프로그래밍실무교육센터


FILTER 연산은 데이터 추출 시 필터링이 일어나고 있음을 알려주는 SQL ROW 연산인데 WHERE 조건 절에서 인덱스를 사용하지 못할 때 발생하는 것입니다. NESTED LOOP 방식으로 해석할 수 있습니다.

아래의 예는 EMP TABLE에서 부서의 최소 급여를 받는 사람들을 추출하는 것입니다.

SQL> SELECT ENAME, SAL, JOB
      FROM   EMPTEST A
      WHERE  SAL = (SELECT MIN(SAL)
                      FROM   EMPTEST B
                      WHERE B.DEPTNO = A.DEPTNO);

Execution Plan
---------------------------------------------------
0       SELECT STATEMENT Optimizer=CHOOSE
1       0  FILTER
2       1     TABLE ACCESS (FULL) OF EMP
3       2     SORT (AGGREGATE)
4       3       TABLE ACCESS (BY INDEX ROWID) OF EMP
5       4         INDEX (RANGE SCAN) OF idx_emp_deptno (NON-UNIQUE) 

ㅍ[ORACLE Hint, 오라클 힌트강좌]ACCESS 경로를 변경하는 힌트(ROWID) ,오라클자바교육,오라클교육

ACCESS 경로를 변경하는 힌트(ROWID)

구로디지털 오엔제이프로그래밍실무교육센터


이 힌트 구문은 ROWID를 이용하여 테이블 스캔이 이루어 지도록 하는 것인데 간단히 예제만 보도록 하겠습니다.

ROWID 힌트를 사용하지 않은 경우 입니다.


[테스트환경]
myemp1 :  2000만건
mydept1 : 5
oracle 11g

-- 먼저 rowid를 알기 위해 데이터 select
SQL>select rowid, empno, sal from myemp1 where rownum < 10

적당한 rowid 값을 입력하여 테스트 하자.


ROWID 힌트를 사용하지 않고 실행하는 경우 index fast full 스캔을 한다.

SQL> select count(empno) from myemp1
  2  where rowid > 'AAASUvAAEAAAMarAAA'
  3    and empno > 1000;

COUNT(EMPNO)
------------
     9999000

   : 00:00:01.59

Execution Plan
---------------------------------------------------------------
|   0 | SELECT STATEMENT      |              |     1 |    17 |  5477   (2)|
|   1 |  SORT AGGREGATE       |              |     1 |    17 |            |
|*  2 |   INDEX FAST FULL SCAN| SYS_C0011302 |   499K|  8299K|  5477  

Myemp1 empno 인덱스를 이용하여 부분 스캔 후 SORT하여 데이터를 추출 한다.


이번에는 실습을 위해 rowid 힌트를 사용해 보자. 너무 느리다.


SQL> select
  2          count(empno) from myemp1
  3  where rowid > 'AAASUvAAEAAAMarAAA'
  4    and empno > 1000  ;

COUNT(EMPNO)
------------
     9999000

   : 00:00:09.93

Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT             |        |     1 |    17 | 16947   (1)|
|   1 |  SORT AGGREGATE              |        |     1 |    17 |            |
|*  2 |   TABLE ACCESS BY ROWID RANGE| MYEMP1 |   499K|  8299K| 16947  


이 경우엔 EMP 테이블에서 ROWID'AAASUvAAEAAAMarAAA'보다 데이터를 찾은 empno 1000보다 데이터를 찾는 실행계획을 만들어 냅니다. 어느 방법이 나은지는 곰곰히 생각해 보세요.



[Oracle SQL Tuning]ACCESS 경로를 변경하는 힌트(HASH) - 오라클힌트 이론 실습

ACCESS 경로를 변경하는 힌트(HASH)

구로디지털 오엔제이프로그래밍실무교육센터


인자로 기술한 테이블에 대해 HASH SCAN이 일어나도록 하는 힌트이며 USE_HASH(해시 조인이 일어나도록 하는 힌트)와 구별되며 HASHKEYS parameter를 가지고 만들어진 CLUSTER내에 저장된 테이블에서만 적용 됩니다.

[형식]
/*+ HASH ( table ) */

[]
[먼저 클러스터를 생성]
CREATE CLUSTER MYEMP2_MYDEPT2_CLUSTER (deptno NUMBER(1))
HASH IS deptno HASHKEYS 150;
  

[실습 테이블을 만들면서 클러스터 저장하기 위해 옵션 정의]
   CREATE TABLE MYDEPT2 (
      deptno NUMBER(1) PRIMARY KEY,
  dname  VARCHAR2(100) NOT NULL)
   CLUSTER MYEMP2_MYDEPT2_CLUSTER (deptno);
  
  
   CREATE TABLE MYEMP2 (
          empno  NUMBER PRIMARY KEY,
         ename  VARCHAR2(100) NOT NULL,
         sal    NUMBER(9),
         deptno NUMBER(1) NOT NULL)
   CLUSTER MYEMP2_MYDEPT2_CLUSTER (deptno);




[테스트를 위한 데이터를 만듭니다.]


insert into mydept2 values (0, '인사팀');
 insert into mydept2 values (1, '회계팀');
 insert into mydept2 values (2, '영업팀');
 insert into mydept2 values (3, '기획팀');
 insert into mydept2 values (4, '교육팀');


commit;


DECLARE
          v_c NUMBER := 1;
BEGIN

          WHILE (v_c <= 10000000) LOOP
                insert into myemp2 values ( v_c, '홍길동'||v_c, mod(v_c, 5), '서울'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp2 values ( v_c, '다길동'||v_c, mod(v_c, 5), '부산'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp2 values ( v_c, '나길동'||v_c, mod(v_c, 5), '대구'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp2 values ( v_c, '나길동'||v_c, mod(v_c, 5), '광주'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
          END LOOP;
          commit;
END;



  
클러스터 인덱스 만들기 전에 일반 인덱스로 먼저 테스트 해보자.
(무지 느리자)

sQL> create index idx_myemp2_deptno on myemp2(deptno)

SQL> SELECT  /*+ index( E idx_myemp2_dept) */
  2             Count(e.ename)
  3     FROM    MYEMP2 E, MYDEPT2 D
  4     WHERE   D.deptno = E.deptno;

COUNT(E.ENAME)
--------------
      10000000

   : 00:01:15.29

Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT       |              |     1 |    26 |     3   (0)|
|   1 |  SORT AGGREGATE        |              |     1 |    26 |            |
|   2 |   NESTED LOOPS         |              |     1 |    26 |     3   (0)|
|   3 |    INDEX FAST FULL SCAN| SYS_C0011304 |     1 |    13 |     2  
|*  4 |    TABLE ACCESS HASH   | MYEMP2       |  2050K|    25M|     1  




이번엔 HASH SCAN 위한 힌트를 사용해 보자.
조금 빨라졌다.

SQL> SELECT 
  2             count(E.ename)
  3     FROM    MYEMP2 E, MYDEPT2 D
  4     WHERE   D.deptno = E.deptno;

COUNT(E.ENAME)
--------------
      10000000

   : 00:01:01.54

Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT       |              |     1 |    26 |     3   (0)|
|   1 |  SORT AGGREGATE        |              |     1 |    26 |            |
|   2 |   NESTED LOOPS         |              |     1 |    26 |     3   (0)|
|   3 |    INDEX FAST FULL SCAN| SYS_C0011304 |     1 |    13 |     2  
|*  4 |    TABLE ACCESS HASH   | MYEMP2       |  2050K|    25M|     1  



Oracle 11g에서 테스트 했을 때 위의 경우 NESTEDD LOOP로 풀리며 또는 힌트를 사용하지 않더라도 EMP TABLE HASH SCAN을 하는 것으로 나타났습니다.

CLUSTER를 확인 할 수 있는 VIEW는 다음과 같구요,

DBA_CLUSTERS         ALL_CLUSTERS         USER_CLUSTERS

아래에 간단한 HASH CLUSTER TABLE에 대한 설명이 있으니 참고 하세요~

다량의 범위를 자주 엑세스해야 하는 경우나 인덱스를 사용한 처리가 부담이 되는 범위(넓은 분포도), 수정이 자주 발생하지 않는 Column, 대규모 테이블, 여러 개의 테이블이 빈번한 조인을 일으킬 때 CLUSTER INDEX를 사용하시면 되는데 HASH CLUSTER에 테이블을 저장하는 것은 데이타 검색의 성능을 향상하기 위한 선택적인 방법 입니다.

Hash Cluster는 인덱스나 인덱스 Cluster를 가지는 Cluster되지 않은 테이블의 대용이며 인덱스 테이블, 인덱스 Cluster와 함께 오라클은 별도의 인덱스에 저장된 키값을 사용하는 테이블 내의 로우(row)에 위치 합니다.

또한 오라클은 물리적으로 Hash Cluster내의 테이블의 로우에 저장하고 Hash function의 결과에 의하여 검색 하는데 특정 Cluster 키값을 바탕으로 Hash Values라 불리는 분산된 수치 값을 생성하는 Hash Function을 사용 한다

[SQL초보실전전문가]조인 방법 변경(USE_MERGE) , 오라클교육,오라클힌트 교육, 자바교육

[Hint]조인 방법 변경(USE_MERGE)
 
구로디지털 오엔제이프로그래밍실무교육센터
 
 
머지 조인(Merge Join)이 일어나도록 유도하는 힌트 구문으로 이 경우 거의 SORT를 동반하므로 SORT MERGE JOIN이라고 부릅니다머지 조인이란 양쪽 테이블에서 대상 로우를 추출 후 조인 컬럼을 기준으로 SORT를 한 후 최종 결과를 만들어 내는 조인 방식 입니다.
 
USE_NL처럼 FROM 절 다음에 위치하는 테이블의 순서는 중요하지 않은데 그 이유는 어차피 독립적으로 정렬된 후 병합이 일어나므로 중요하지 않다고 할 수 있으며 SORT MERGE JOIN에서는 드라이빙 테이블의 의미가 없습니다.
 
[형식]
 
 
[]
아래 예제는 Oracle 10g에서 돌렸습니다.
 
 
select 
       e.empno,
          e.ename,
          d.dname,
          d.loc
from   dept d, emp e
where  e.deptno = d.deptno
 
---------------------------------------------------------------
Operation            Object Name      Rows     Bytes    Cost     
-------------------------------------------------------------
SELECT STATEMENT Optimizer Mode=ALL_ROWS               14                      5
  MERGE JOIN                  14         406       5                                                       
    TABLE ACCESS BY INDEX ROWID         SCOTT.DEPT      4           72         2            
      INDEX FULL SCAN   SCOTT.PK_DEPT             4                        1            
    SORT JOIN                 14         154       3                                                       
      TABLE ACCESS BY INDEX ROWID      SCOTT.EMP        14         154       2            
        INDEX FULL SCAN             SCOTT.IDX_EMP_DEPTNO            13                      1                                                           
 
select 
       e.empno,
          e.ename,
          d.dname,
          d.loc
from   dept d, emp e
where  e.deptno = d.deptno
 
---------------------------------------------------------------------
Operation            Object Name      Rows     Bytes    Cost     
------------------------------------------------------------------
SELECT STATEMENT Optimizer Mode=ALL_ROWS               14                      5
  MERGE JOIN                  14         406       5                                                       
    TABLE ACCESS BY INDEX ROWID         SCOTT.DEPT      4           72         2            
      INDEX FULL SCAN   SCOTT.PK_DEPT             4                        1                SORT JOIN                14         154               3                                                       
      TABLE ACCESS BY INDEX ROWID      SCOTT.EMP        14         154       2            
        INDEX FULL SCAN             SCOTT.IDX_EMP_DEPTNO            13                      1                                                           
 
[실습]
 
-      실습을 위한 예제 테이블 및 데이터는 아래 링크에서 확인 바랍니다.
 
myemp1 : 1000만건
myemp1_old : 100만건
mydept : 5
 
테스트환경 : oracle 11g
 
 
MYEMP1이 비드라이빙 테이블이지만 머지조인 에서는 별 의미 없다.
 
SQL> select
  2         e.ename,
  3         d.dname
  4  from   mydept1 d, myemp1 e
  5  where  e.deptno = d.deptno   ;
 
20000000 개의 행이 선택되었습니다.
 
   : 00:02:22.62
 
 
---------------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |    20M|   476M|       | 68516   (2)| 00:13:43 |
|   1 |  MERGE JOIN         |         |    20M|   476M|       | 68516   (2)| 00:13:43 |
|   2 |   SORT JOIN         |         |    10 |   100 |       |     4  (25)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| MYDEPT1 |    10 |   100 |       |     3   (0)| 00:00:01 |
|*  4 |   SORT JOIN         |         |    10M|   143M|   459M| 68463   (1)| 00:13:42 |
|   5 |    TABLE ACCESS FULL| MYEMP1  |    10M|   143M|       | 16941   (1)| 00:03:24 |
 
 
SQL> select
  2         e.ename,
  3         d.dname
  4  from   myemp1 e, mydept1 d
  5  where  e.deptno = d.deptno ;
 
20000000 개의 행이 선택되었습니다.
 
   : 00:02:09.58
 
---------------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |    20M|   476M|       | 68516   (2)| 00:13:43 |
|   1 |  MERGE JOIN         |         |    20M|   476M|       | 68516   (2)| 00:13:43 |
|   2 |   SORT JOIN         |         |    10M|   143M|   459M| 68463   (1)| 00:13:42 |
|   3 |    TABLE ACCESS FULL| MYEMP1  |    10M|   143M|       | 16941   (1)| 00:03:24 |
|*  4 |   SORT JOIN         |         |    10 |   100 |       |     4  (25)| 00:00:01 |
|   5 |    TABLE ACCESS FULL| MYDEPT1 |    10 |   100 |       |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------