이진탐색+Recrusion (되부름 알고리즘)

 

 

#include <iostream>
#include <iomanip>
using namespace std;

bool bi_Iterative(int list[], int end, int target, int & locn);

bool bi_Recursive();

const int SIZE=100;

int main(void)
{
int list[SIZE];

int srchArgu;
int foundLocn;

//배열 채우기

for(int i=0; i < SIZE; i++)
{
list[i]=2*i;
}
for(int i=0; i < SIZE; i++)
{
if(i%10==0)
{
cout<<endl;
}
else
{
cout<<setw(4)<<list[i];
}
}

cout<<endl<<"원하는 숫자입력:";
cin>>srchArgu;

bool res=bi_Recursive(list, SIZE-1,srchArgu,foundLocn);
if(res ==true)
{
cout<<"데이터 찾음"<<list[foundLocn]<<endl;
}
else
{
cout<<srchArgu<<"데이터를 못찾음"<< endl;
}
}
//
//bool bi_Iterative(int list[], int end, int target, int & locn)
//{
// int first=0, mid, last=end;
//
//
// while(first<=last)
// {
// mid=(first+last)/2;
//
// if(target>list[mid])
// {
// first=mid+1;
// }
// else if(target<list[mid])
// {
// last=mid-1;
// }
// else
// {
// break;
// }
// }
//
// locn=mid;
//
// return (target == list[mid]);
//
//}



bool bi_Recursive(int list[], int end, int target, int & locn)
{
int first=0, mid, last=end;
mid=(first+last)/2;

if(first<=last)
{
if(target == list[mid])
{
return (target == list[mid]);
}
else if(target>list[mid])
{
first=mid+1;
bi_Recursive(list,mid,first,locn);
}
else if(target<list[mid])
{
last=mid-1;
bi_Recursive(list,last,mid,locn);
}

}

locn=mid;

}
블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,


C# 채팅 프로그램(Server)
 


using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Threading;


namespace Ex_chatserver

{

    public partial class MainForm : Form

    {


        private delegate void AddTextDelegate(String strText); // Cross-Thread 호출을 실행하기 위해사용


        public MainForm()

        {

            InitializeComponent();

        }


        private void Form1_Load(object sender, EventArgs e) //form1이 로드되면서 시작.

        {

            //서버를 시작

            Thread t1 = new Thread(new ThreadStart(StartListen));

            t1.Start();


        }

        


        private void StartListen()

        {

            IPAddress addr = new IPAddress(long.Parse("127.0.0.1")); //ip주소받기

            TcpListener Server = new TcpListener(addr, 8080);


            AddTextDelegate AddText = new AddTextDelegate(txtClient.AppendText);


            String MessageStr = "안녕하세요, 서버에서 보냅니다.";


            Server.Start();//연결요청 대기시작


            Invoke(AddText, "Listening을 시작합니다..\r\n");


            TcpClient Client = Server.AcceptTcpClient();//연결요청수락

            Invoke(AddText, "Client와 연결되었습니다..\r\n");


            NetworkStream stream = Client.GetStream();//NetWorkStream 얻기


            StreamWriter writer = new StreamWriter(stream);//메시지 보내기

            writer.WriteLine(MessageStr);

            writer.Flush();

            Invoke(AddText, "Client에 메시지를 보냈습니다..\r\n");


            Client.Close();//연결닫기

            Server.Stop();

            Invoke(AddText, "서버와 연결 종료..\r\n");


            //TcpListener는 Client의 요청에 귀기울(Listen)이고 있다가 Client가 연결을 요청해오면(Connect) Client의 연결요청을 수락(AcceptTcpClient)합니다.

            //여기까지 진행되고 나면 실제 데이터를 주고 받는 통신은 NetWorkStream을 통해서 이루어짐.

        }

       

    }

}



참고자료
 

비주얼 C# 2005 익스프레스로 배우는 C# 2.0 프로그래밍 
MSDN http://msdn.microsoft.com/ko-kr/default.aspx 


블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,

Explain Plan란?
  • Explain plan은 QL문의 엑세스 경로를 확인하고 튜닝할 수 있도록 SQL문을 분석하고 해석하여 실행계획을 수립한 후 실행계획을PLAN_TABLE에 저장하도록 해주는 명령이다.
  • SQL Trace 없이 사용 할 수 있다.
     
  • EXPLAIN Plan문법

       

Explain plan[set statement_id = 'identifier' ]

[ Into tablename ]

For sql statement

  

   

Explain plan Set statement_id='a1' For

Select /*+ use_nl(emp dept) */ *

From emp, dept Where emp.deptno = dept.deptno And emp.deptno=10;

  

   

  • statement_id = 'identifiedr' : 1-30자로 부여할 수 있는 해당 실행문의 제목
  • INTO tablename : 출력문을 저장하는 테이블명 PLAN_TABLE을 사용하지 않을경우 사용
  • FOR statement : 실행계획을 수립하고자 하는 SQL문(SELECT, INSERT, DELETE, UPDATE)

       

  • EXPLAIN 설치

       

    EXPLAIN PLAN 을 설치하면 $ORACLE_HOME/rdbms/admin에 다수의 스크립트가 포함된다.

       

    PLAN_TALBE이라 명명된 테이블의 CREATE TABLE문을 포함하고 있는 utlxplan.sql(UTiLility

    eXplain의 줄임말)

    병렬 쿼리 계획에 특화된 정보를 포함하여 계획 테이블의 내용을 보여 주는 utlxplp.sql(UTiLtility eXplain Plan Parallel의 줄임말)

    일반적인 직렬(비병렬) 계획에 대한 계획 테이블의 내용을 보여 주는 utlxpls.sql(UTiLity eXplain PLan으 줄임말)

    • EXPLAIN PLAN을 설정하기 위해서는 먼저 PLAN_TABLE을 만들어야 한다. PLAN_TABLE 생성은 오라클에서 스크립트로 제공해 주고 있다.

       

SQL > @C:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\utlxplan

  

   

   

Global Temporary 생성

Gloal Temporary란?

  • 임시 테이블은 사용자가 DML(update, insert, delete) 문을 실행한 후, 트랜젝션을 종료(commit)하면 변경된 데이터들이 테이블에 저장되지 않는 테이블이다

       

Create 문법

Create Global Temporary Table <table_name>(

<column_name> <column_data_type>,

<column_name> <column_data_type>,

<column_name> <column_data_type>)

[ON COMMIT DELETE ROWS | ON COMMIT PRESERVE ROWS];

  

   

  • on commit delete rows : 트랜젝션을 발생시킨 후, commit문을 실행할 때 없어지는 방법, 한 transaction 동안만 data를 저장(default임)
  • on commit preserve rows : 트랜젝션을 종료하면(commit) 테이블 내에 데이터가 저장되었다가 세션을 종료하면 임시 테이블에 저장되었던 데이터들이 모두 없어지는 방법

    한 session 동안만 data를 저장

       

    • Temporary Table?
      • 특정 Session 또는 Transaction 동안만 data를 저장함.
      • TABLE의 definition 정보는 data dictionary에 영구적으로 저장되지만, data는 일시적으로 저장된다.
      • CREATE로 TABLE 생성시 SEGMENT가 할당되는 것이 아니라 첫 번째 INSERT시 할당된다.
      • DML 작업 시 해당 data에 대해 LOCK을 걸지 않는다.
      • data 변경 시 redo log에 기록이 남지 않는다.

           

CREATE GLOBAL TEMPORARY TABLE PLAN_TABLE (
statement_id varchar2(30),
plan_id number,
timestamp date,
remarks varchar2(4000),
operation varchar2(30),
options varchar2(255),
object_node varchar2(128),
object_owner varchar2(30),
object_name varchar2(30),
object_alias varchar2(65),
object_instance numeric,
object_type varchar2(30),
optimizer varchar2(255),
search_columns number,
id numeric,
parent_id numeric,
depth numeric,
position numeric,
cost numeric,
cardinality numeric,
bytes numeric,
other_tag varchar2(255),
partition_start varchar2(255),
partition_stop varchar2(255),
partition_id numeric,
other long,
distribution varchar2(30),
cpu_cost numeric,
io_cost numeric,
temp_space numeric,
access_predicates varchar2(4000),
filter_predicates varchar2(4000),
projection varchar2(4000),
time numeric,
qblock_name varchar2(30),
other_xml clob
)

ON COMMIT PRESERVE ROWS;

-- 모든권한
grant ALL on PLAN_TABLE 모든유저;

-- 동의어 생성 : PUBLIC SYNONYM 을 생성할수 있는 권한이 있는 유저로 가야한다.
CREATE PUBLIC SYNONYM PLAN_TABLE FOR PLAN_TABLE;

  

   

  • PLAN_TABLE 컬럼 설명

컬 럼 명

설 명

STATEMENT_ID

EXPLAIN PLAN문에서 사용자가 지정한 제목

TIMESTAMP

실행계획이 수립된 날짜와 시간

REMARKS

사용자가 부여한 주석(COMMENT)

OPERATION

아래 표에 자세히 설명 되어 있습니다.

OPTIONS

아래 표에 자세히 설명 되어 있습니다.

OBJECT_NODE

사용한 데이터베이스 링크

OBJECT_OWNER

해당 라인의 오브젝트를 생성한 사용자 그룹

OBJECT_NAME

테이블이나 인덱스, 클러스터등의 이름

OBJECT_INSTANCE

SQL의 FROM절에 기술된 오브젝트를 좌에서 우로 부여한 번호

OBJECT_TYPE

오브젝트의 종류(예 non-unique index)

ID

수립된 각 실행단계에 붙여진 일련번호

PARENT_ID

해당 ID의 부모가 가진 ID

POSITION

같은 부모 ID를 가지고 있는 자식 ID간의 처리 순서

OTHER

다른 필요한 텍스트를 지정하기 위한 필트

   

  • Explain Plan 실행

       

SQL> Explain plan Set statement_id='a1' For

Select /*+ use_nl(emp dept) */ *

From emp, dept Where emp.deptno = dept.deptno And emp.deptno=10;

해당 SQL문

SQL> def id = a12

ID값 지정

SQL> SELECT LPAD(operation,LENGTH(operation)+ 2*(LEVEL-1)) ||DECODE(id,0,'cost estimate:' ||
DECODE(position,'0','N/A',position),null) || ' ' ||options || DECODE(object_name,null,null,':') ||
RPAD(object_owner, LENGTH(object_name)+1,',') || object_name ||
DECODE (object_type,'UNIQUE' ,'(U) ','NON_UNIQUE','(NU)',null) ||
DECODE(object_instance,null,null,'('||object_instance||')') "Explain Plan"
FROM PLAN_TABLE
START WITH ID= 0 and STATEMENT_ID = '&&id'
CONNECT by prior ID=PARENT_ID and STATEMENT_ID='&&id'

  

   

SQL> Explain plan Set statement_id='a1' For

2 Select /*+ use_nl(emp dept) */ *

3 From emp, dept Where emp.deptno = dept.deptno And emp.deptno=10;

   

해석되었습니다.

   

SQL> def id=a1

   

SQL> SELECT LPAD(operation,LENGTH(operation)+ 2*(LEVEL-1)) ||DECODE(id,0,'cost estimate:' ||

2 DECODE(position,'0','N/A',position),null) || ' ' ||options || DECODE(object_name,null,null,':') ||

3 RPAD(object_owner, LENGTH(object_name)+1,',') || object_name ||

4 DECODE (object_type,'UNIQUE' ,'(U) ','NON_UNIQUE','(NU)',null) ||

5 DECODE(object_instance,null,null,'('||object_instance||')') "Explain Plan"

6 FROM PLAN_TABLE

7 START WITH ID= 0 and STATEMENT_ID = '&&id'

8 CONNECT by prior ID=PARENT_ID and STATEMENT_ID='&&id';

구 7: START WITH ID= 0 and STATEMENT_ID = '&&id'

신 7: START WITH ID= 0 and STATEMENT_ID = 'a1'

구 8: CONNECT by prior ID=PARENT_ID and STATEMENT_ID='&&id'

신 8: CONNECT by prior ID=PARENT_ID and STATEMENT_ID='a1'

   

Explain Plan

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

SELECT STATEMENTcost estimate:4

NESTED LOOPS

TABLE ACCESS BY INDEX ROWID:SYS,,DEPT(2)

INDEX UNIQUE SCAN:SYS,,,,,DEPT_U1

TABLE ACCESS BY INDEX ROWID:SYS,EMP(1)

INDEX RANGE SCAN:SYS,,,,EMP_N1

   

6 개의 행이 선택되었습니다.

   

SQL> exit

  

   

  • PERATION의 종류와 OPTIONS에 대한 설명

OPERATION(기능)

OPTIONS(옵션)

설 명

AGGREGATE

GROUP BY

그룹함수를 사용하여 하나의 로우가 추출되도록 하는 처리(버전 7에서만 표시됨)

AND-EQUAL

  

인덱스 머지를 이용하는 경우

CONNECT BY

  

CONNECT BY를 사용하여 트리 구조로 전개

CONCATENATION

  

단위 액세스에서 추출한 로우들의 합집합을 생성

COUNTING

  

테이블의 로우스를 센다

FILTER

  

선택된 로우에 대해서 다른 집합에 대응되는 로우가 있다면 제거하는 작업

FIRST ROW

  

조회 로우 중에 첫번째 로우만 추출한다.

FOR UPDATE

  

선택된 로우에 LOCK을 지정한다.

INDEX

INQUE

UNIQUE인덱스를 사용한다. (단 한개의 로우 추출)

  

RANGE SCAN

NON-UNIQUE한 인덱스를 사용한다.(한 개 이상의 로우)

  

RANGE SCAN

DESCENDING

RANGE SCAN하고 동일하지만 역순으로 로우를 추출한다.

NTERSECTION

  

교집합의 로우를 추출한다.

MERGE JOIN

  

먼저 자신이ㅡ 조건만으로 액세스한 후 각각을 SORT하여 MERGE해 가는 조인

  

OUTER

위와 동일하지만 outer join을 사용한다

MINUS

  

MINUS 함수를 사용한다.

NESTED LOOPS

  

먼저 어떤 드라이빙 테이블의 로우를 액세스한 후 그 결과를 이용해 다른 테이블을 연결하는 조인

  

OUTER

위와 동일하지만 outer join을 사용한다.

PROJECTION

  

내부적인 처리의 일종

REMOTE

  

다른 분산 데이터베이스에 있는 오브젝트를 추출하기 위해 DATABASE LINK를 사용하는 경우

SEQUENCE

  

시퀀스를 액세스 한다.

SORT

UNIQUE

같은 로우를 제거하기 위한 SORT

  

GROUP BY

액세스 결과를 GROUP BY 하기 위한 SORT

  

JOIN

MERGE JOIN을 하기 위한 SORT

  

ORDER BY

ORDER BY를 위한 SORT

TABLE ACCESS

FULL

전체 테이블을 스캔한다.

  

CLUSTER

CLUSTER를 액세스 한다.

  

HASH

키값에 대한 해쉬 알고리즘을 사용(버전 7에서만)

  

BY ROWID

ROWID를 이용하여 테이블을 추출한다.

UNION

  

두 집합의 합집합을 구한다.(중복없음) 항상 전체 범위 처리를 한다.

UNION ALL

  

두 집합의 합집합을 구한다.(중복가능) UNION과는 다르게 부분범위 처리를 한다.

VIEW

  

어떤 처리에 의해 생성되는 가상의 집합에서 추출한다.(주로 서브쿼리에 의해 수행된 결과)

  • DBMS_XPLAN Package
    • DBMS_XPLAN은 EXPLAIN PLAN 구문보다 확장된 정보를 보여준다.
    • Oracle 9.2버젼에 소개되었으며 plan_table에 저장된 실행계획을 좀 더 쉽게 출력해 볼 수 있게 되었다.
    • DBMS_XPLAN Package에서 제공하는Procedure
    • DISPLAY
    • DISPLAY_CURSOR
    • DISPLAY_AWR
    • DISPLAY_SQLSET
    • PREPARE_RECORDS
    • VALIDATE_FORMAT

         

    • 이 Package를 사용하기 위해서는 아래의 객체에 SELECT권한이 있어야 한다.
    • V$SESSION
    • V$SQL_PLAN
    • V$SQL(optional)
    • V$SQL_PLAN_STATISTICS_ALL
    • @$ORACLE_HOME/rdbms/admin/ultxpls 스크립트를 열여보면 내부적으로 DBMS_XPLAN Package를 호출하고 있는것을 볼 수 있다.

         

select plan_table_output from table(dbms_xplan.display('plan_table',null,'serial'))

  

  • DBMS_XPLAN.DISPLAY
    • DBMS_XPLAN.DISPLAY는 단일 SQL문에 대해 예측 실행계획을 보여주는 Function 이다.
    • DBMS_XPLAN.DISPLAY는 실측 정보가 아닌 예측 정보를 제공한다.
    • Function Parameter

FUNCTION DISPLAY(TABLE_NAME VARCHAR2 DEFAULT 'PLAN_TABLE',
STATEMENT_ID VARCHAR2 DEFAULT NULL,
FORMAT VARCHAR2 DEFAULT 'TYPICAL',
FILTER_PREDS VARCHAR2 DEFAULT NULL)


 

   

  • 파라미터 설명

파라미터

  

설명

TABLE_NAME

  

Execution Plan이 저장되는 테이블을 지정하며, 기본값은 'PLAN_TABLE' 이다.

STATEMENT_ID

  

Execution Plan시 SET STATEMENT_ID를 지정한 경우 이를 불러올 수 있다. 

값이 NULL일 경우 마지막에 실행된 문장을 불러온다.

FORMAT

BASIC

가장 기본적인 정보만 보여 준다.

  

TYPICAL

Format의 Default값인 Typical은 SQL 튜닝에 필요한 Normal한 정보를 보여 준다. 

SQL 튜닝에 가장 유용하게 사용되는 Predicate Information이 제공 된다.

  

ALL

Typical Format에 Query Block Name과 Column Projection Information이 추가로 제공된다

  

OUTLINE

Typical Format에 추가적으로 Hidden Hint인 Outline Global Hint를 제공한다

  

ADVANCED

ALL Format에 OUTLINE Format를 합친 정보를 제공한다

FILTER_PREDS

  

저장된 PLAN에서 일부 Row 또는 Row Set을 제한하여 출력할 수 있다.

   

  • 사용방법

       

    Explain plan [set statement_id = 'identifier' ] [ Into tablename ] for + SQL;

    • 분석하고자 하는 SQL을 'Explain plan for' 다음에 넣고 Enter

         

    Select * from Table(DBMS_XPLAN.DISPLAY);

    • SQL이 Explain 되었으면 그 다음에 원하는 포맷으로 출력하기 위해서 위와 같이 기본적으로 'PLAN_TABLE'과 'TYPICAL' Format으로 출력.

         

SQL>

SQL> explain plan for

2 select /*+ use_nl(emp dept) */ * from emp, dept

3 where emp.empno=dept.deptno

4 and emp.deptno=10;

   

해석되었습니다.

   

SQL> select * from table(dbms_xplan.display('plan_table',null,'typical',null));

   

   

PLAN_TABLE_OUTPUT

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

Plan hash value: 3431005640

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

   

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

   

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

PLAN_TABLE_OUTPUT

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

| 0 | SELECT STATEMENT | | 1 | 57 | 3 (0)| 00:00:01 |

| 1 | NESTED LOOPS | | 1 | 57 | 3 (0)| 00:00:01 |

| 2 | TABLE ACCESS FULL | DEPT | 4 | 80 | 3 (0)| 00:00:01 |

|* 3 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 37 | 0 (0)| 00:00:01 |

   

PLAN_TABLE_OUTPUT

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

|* 4 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)| 00:00:01 |

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

   

Predicate Information (identified by operation id):

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

   

PLAN_TABLE_OUTPUT

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

3 - filter("EMP"."DEPTNO"=10)

4 - access("EMP"."EMPNO"="DEPT"."DEPTNO")

   

17 개의 행이 선택되었습니다.

  

   

여기서 잠깐~! Predicate Information에 나오는 Access,Filter Predicate에 대해 알아보자~!

  • *Access Predicate*는 Access Type을 결정하는데 사용되는 Predicate(조건)을 의미한다. 더 정확하게 말하면 실제 Block을 읽기 전에 어떤 방법으로 Block을 읽을 것인가를 결정한다는 의미이다.
    따라서 Index Lookup이나 Join등은 Access Predicate로 표현된다.
  • *Filter Predicate*는 실제 Block을 읽은 후 Data를 걸러 내기 위해 사용되는 Predicate(조건)를 의미한다.

       

  • Predicate Information test

       

SQL>

SQL> explain plan for

2 select /*+ use_nl(emp dept) */ * from emp, dept

3 where emp.empno=dept.deptno

4 and emp.deptno=10;

   

해석되었습니다.

   

SQL> select * from table(dbms_xplan.display('plan_table',null,'typical',null));

   

PLAN_TABLE_OUTPUT

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

Plan hash value: 3431005640

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

   

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

   

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

PLAN_TABLE_OUTPUT

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

| 0 | SELECT STATEMENT | | 1 | 57 | 3 (0)| 00:00:01 |

| 1 | NESTED LOOPS | | 1 | 57 | 3 (0)| 00:00:01 |

| 2 | TABLE ACCESS FULL | DEPT | 4 | 80 | 3 (0)| 00:00:01 |

|* 3 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 37 | 0 (0)| 00:00:01 |

   

PLAN_TABLE_OUTPUT

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

|* 4 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)| 00:00:01 |

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

   

Predicate Information (identified by operation id):

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

   

PLAN_TABLE_OUTPUT

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

3 - filter("EMP"."DEPTNO"=10)

4 - access("EMP"."EMPNO"="DEPT"."DEPTNO")

   

17 개의 행이 선택되었습니다.

  

   

SQL>

SQL> explain plan for

2 select /*+ use_hash(emp dept) */ * from emp, dept

3 where emp.empno=dept.deptno

4 and emp.deptno=10;

   

해석되었습니다.

   

SQL> select * from table(dbms_xplan.display('plan_table',null,'typical',null));

   

   

PLAN_TABLE_OUTPUT

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

Plan hash value: 1123238657

   

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

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

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

| 0 | SELECT STATEMENT | | 1 | 57 | 7 (15)| 00:00:01 |

|* 1 | HASH JOIN | | 1 | 57 | 7 (15)| 00:00:01 |

|* 2 | TABLE ACCESS FULL| EMP | 3 | 111 | 3 (0)| 00:00:01 |

| 3 | TABLE ACCESS FULL| DEPT | 4 | 80 | 3 (0)| 00:00:01 |

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

   

PLAN_TABLE_OUTPUT

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

Predicate Information (identified by operation id):

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

   

1 - access("EMP"."EMPNO"="DEPT"."DEPTNO")

2 - filter("EMP"."DEPTNO"=10)

   

16 개의 행이 선택되었습니다.

  

   

  • 왜 Nested Loops Join과 Hash Join에서 Access Predicate가 표현되는 방식의 차이가 발생하는가? 
    두 Join의 동작방식의 차이에서 비롯된다.

구분

방식

결론

Nested Loops Join

선행 Table읽으면서 후행 Table을 한번씩 Access

실제 Join은 후행 Table에 대한 Access에서 발생하기 때문에 실제 Join은 후행 Table에 대한 Acccess에서 발생한다. 

그러므로 후행 Table을 읽는 단계가 Access Predicate가 된다.

Hash Join

선행 Table을 먼저 Build한 후, 후행 Table과 한번에 Join

실제 Join이 발생하는 Hash Join 단계가 Access Predicat로 표현된다.

   

  • FORMAT

       

구분

FORMAT

내용

예측내용

BASIC

DBMS_XPLAN.DISPLAY 포멧과 같은 내용

예측내용

TYPICAL

DBMS_XPLAN.DISPLAY 포멧과 같은 내용

예측내용

ALL

DBMS_XPLAN.DISPLAY 포멧과 같은 내용

예측내용

OUTLINE

DBMS_XPLAN.DISPLAY 포멧과 같은 내용

예측내용

ADVANCED

DBMS_XPLAN.DISPLAY 포멧과 같은 내용

실측내용

ALLSTATS

실제 액세스한 로우수와 수행시간 그리고 CR, PR, PW 정보를 보여준다.

수행횟수에 따라 *누적된 값*을 보여준다

실측내용

ALLSTATS LAST

실제 액세스한 로우수와 수행시간 그리고 CR, PR, PW 정보를 보여준다.

*가장 최근*에 수행된 값만 보여준다.

실측내용

ADVANCED ALLSTATS LAST

DBMS_XPLAN.DISPLAY_CURSOR에서 지원하는 모든 Format의

정보를 보여준다.

   

   

<참고문헌>

Oracle Database 11g : Adminstration Workshop

Oracle Database 10g Documentation Library - councepts

원본 위치 <http://www.oracleclub.com>

원본 위치 <http://www.oracleclub.com/lecture/1017>

원본 위치 <http://www.gurubee.net/display/DBSTUDY/EXPLAIN+PLAN>

블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,


1. SQL과 옵티마이저

  • 논리적으로 처리 가능한 경로는(인덱스, 클러스터, 옵티마이져 모드, 수립된 통계정보, SQL문장과 형태, 시스템 및 네트워크 상태 등) 여러가지에 의해 종합적으로 감안하여 옵티마이져가 실행 계획을 수립.

       

  • 선택성에 가장 중요하게 미치는 정보는 컬럼값들에 대한 차별적인 분포도(밀도)와 엑세스의 분류 단가 즉 클러스터 팩터 부분이다.

       

    • Clustering Factor 란 Index의 Table에 대한 정렬 정도이다. 이것은 Index를 Scan하는 동안 방문(ACCESS)하게 되는 Table의 Data Block의 개수이다. 즉 넓은 범위의 Data를 Index를 경유해서 읽을 경우, Clustering Factor가 Physical Reads의 발생 빈도에 큰 영향을 미친다.

         

  • 옵티마이저가 가장 실행 계획을 수립하는데 절대적으로 영향을 미치는 것은 가장 최소량을 처리할 수 있도록 하는 것과 가장 싼값으로 엑세스 할 수 있느냐가 가장 큰 요소이다.

       

  • 옵티마이져와 우리의 역할
  • SQL이라는 언어로 요구를 하면 DBMS는 최적의 경로를 사용하여 결과를 보여준다. 여기서 최적의 경로를 계산하는 부분이 옵티마이져의 역할이다.

       

  • 사용자가 준비해 두어야 할 기본적인 옵티마이징 팩터는 인덱스 구성에 대한 전략과 적절한 SQL을 작성하는 것이다. 그러나 적절한 판단을 하기 위해서는 실행 계획을 이해하고, 제어하기 위해서 옵티마이져를 알아야 한다.

       

  • 옵티마이져의 형태
    • 규칙기준 옵티마이져(RBO, Rule Based Optimizer)
      • 인덱스 구조나 비교연산자에 따라 순위를 부여하여 이것을 기준으로 최적의 결정을 결정.

           

        • ROWID 1 로우 액세스
        • 클러스터 조인에 의한 1 로우 액세스
        • Unique HASH Cluster 의한 1 로우 액세스
        • Unique Index 의한 1 로우 엑세스
        • Cluster 조인
        • Non Unique Hash cluster key
        • Non Unique cluster key
        • Non Unique 결합 인덱스
        • Non unique 컬럼 인덱스
        • index 의한 범위처리
        • index 의한 전체범위처리
        • Sort Merge 조인
        • 인덱스 컬럼의 Min, MAX 처리
        • 인덱스 컬럼의 order by
        • 전체테이블 스캔

           

      • 같은 랭킹이라면 Where절은 뒤에서 부터, From절도 뒤의 객체가 우선순위를 갖는다.

           

      • 한 객체(테이블)아ㅔ서 같은 랭킹의 인덱스가 있다면 가장 최근에 만들어진 인덱스를 사용

           

      • 장점
        • 사용자가 문제점을 미리 예측하고 자신이 원하는 방법으로 실행계획을 제어하기 쉽다.
        • 전략적인 인덱스를 구성하여 SQL를 구성 하였을 경우 다른 요소에 실행 계획이 변동되는 변수가 적다.

             

      • 단점
        • 현실적인 요소를 무시하여 개산하므로 판단 오차가 크게 나타날 수 있음.

           

           

    • 비용기준 옵티마이져(CBO, Cost Based Optimizer)
      • 통계 정보를 바탕으로 실제의 Cost비용을 산출, 비교하여 최소비용이 드는 방식 선택

           

      • 통계 정보 형태, 종류 DBMS, Version에 따라 차이는 있지만 보통 테이블의 로우 수, 블록 수 블록당 평균 로우수, 로우의 평균길이, 컬럼별 상수값의 종류, 분포도, 컬럼 내 Null 값의 수, 클러스터링 팩터, 인덱스의 깊이, 최소 최대 값, 리프 블럭수, 가동시스템의 I/O, CPU사용정보 등을 가지고 있다.

           

      • 장점
        • 현실을 감안한 판단을 할 수 있다는 것
        • 통계정보의 관리를 통해 최적화를 제어 할 수 있다.
        • 옵티마이져를 깊이 이해하고 있지 않더라도 최소한의 성능이 보장된다.

             

      • 단점
        • 실행계획을 미리 예측하기 어렵다.
        • 버전에 따라 변화가 심하다.
        • 실행게획의 제어가 어렵다.

         

  • 실행계획의 고정화(Stability)
    • 아우트라인(Outline)
      • 과거에 수립되었던 실행계획의 요약본을 저장하고 있다가 이것을 참조하여 실행 계획을 수립하는 기능

           

      • 일반적으로 통계정보의 변화에 따라 변동되는 실행계획을 최적화된 실행계획으로 고정시키고자 하는 용도로 사용

           

    • 아우트라인 사용의 바람직한 방법
      • 잘 정비된 옵티마이징 팩터와 적절한 SQL을 기반으로 대부분의 경우는 옵티마이저에게 맡기고 특별히 문제가 있는 경우에 대해서만 아우트라인으로 통제
        • 카테고리(Category): Outline의 선별적인 적용을 가능하게 하기 위하여 지정한 그룹

             

  • 옵티마이저의 최적화 절차
    • 옵티마이져의 목표
      • 사용자가 요구한 결과를 가장 최소의 자원으로 처리할 수 있는 방법을 찾아내는 것.

           

    • 옵티마이저 처리 과정
      • 최초 실행한 SQL은 딕셔너리를 참조하여 파싱을 수행 -> 옵티마이져는 파싱된 결과를 이용해 논리적으로 적용 가능한 실행 계획 형태를 골라내고, 힌트를 감안하여 일차적으로 잠정적인 실행계획들을 생성
      • 통계정보를 기반으로 데이터의 분포도와 테이블의 저장 구조의 특성, 인덱스 구조, 파티션 형태, 비교 연산자 등을 감안하여 각 실행계획의 비용을 계산-> 비용의 계산에는 컴퓨터의 자원(I/O, CPU,Memory)도 함께 감안됨
      • 비용이 산출된 실행계획들을 비교하여 가장 최소의 비용을 가진 실행 계획을 선택

           

    • 질의 변환기
      • 질의의 변환
      • 이행성규칙
      • 뷰병합 등… 보충필요

         

    • 비용 산정기
      • 선택도(Selectivity)
        • 처리할 대상 집합에서 해당 조건을 만족하는 로우가 차지하는 비율
        • 히스토그램 정보 유무에 따라 선택도 계산 방식은 달라짐

히스토그램정보가 없는 경우

통계정보만을 이용하여 선택도를 계산

히스토그램정보가 있는 경우

미리 계산된 분포값을 직접활용

  • 카디널리티(Cardinality)
    • 판정 대상이 가진 결과건수 혹은 다음 단계로 들어가는 중간결과건수를 의미
    • 위에서 계산한 선택도(Selectivity)와 전체 로우 수(Num_rows)를 곱해서 계산

     

  • 비용(Cost)
    • 각 연산들을 수행할 때 소요되는 시간비용을 상대적으로 계산한 예측치
    • 스키마 객체에 대한 통계정보에 추가적으로 CPU와 메모리 상황, Disk I/O비용도 고려되어 계산

         

  • 실행 계획 생성기
  • 적용 가능한 실행 계획을 선별하고 비교 검토를 거쳐 가장 최소의 비용을 가진 것을 선택
  • 다양한 적용 가능한 실행계획 형태에 대해 비교평가를 하지만 그렇다고 해서 논리적을 존재하는 모든 것에 대해 시도를 하지는 않는다.

       

    • 실행 계획 생성기는 아래의 두가지 전략을 사용
      • 쿼리 수행에 예상되는 총 수행시간에 비해 최적화에 소요되는 시간이 일정비율을 넘지 않도록 함.
      • 탐색 도중 최적이라고 발생하면 실행계획을 더 이상 진행하지 않고 멈춤.

   

<참고문헌>

Oracle Database 11g : Adminstration Workshop

Oracle Database 10g Documentation Library - councepts

원본 위치 <http://www.oracleclub.com>

원본 위치 <http://www.gurubee.net/pages/viewpage.action?pageId=12353616>

블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,

서브쿼리(Subquery)란?

   

  • 서브쿼리란?

- 서브쿼리는 다른 하나의 SQL 문장의 절에 NESTEDED된 SELECT 문장 이다.

SELECT, UPDATE, DELETE, INSERT와 같은 DML문과 CREATE TABLE 또는 VIEW에서 이용 될 수 있다.

- 알려지지 않은 조건에 근거한 값 들을 검색하는 SELECT 문장을 작성하는데 유용 하다.

  • 가이드라인

- 서브쿼리는 괄호로 묶어야 한다.

- 단일 행 연산자(=, >, >=, <, <=, <>, !=)와 복수 행 연산자(IN, NOT IN, ANY, ALL, EXISTS)들이 서브쿼리에 사용 된다.

- 서브쿼리는 연산자의 오른쪽에 위치해야 한다.

  • 서브쿼리의 유형

단일 행(Sing-Row) 서브쿼리 : SELECT 문장으로 부터 오직 하나의 행 만을 검색하는 질의이다.

다중 행(Multiple-Row) 서브쿼리 : SELECT문장으로부터 하나 이상의 행을 검색하는 질의이다.

다중 열(Multiple-Column) 서브쿼리 : SELECT문장으로부터 하나 이상의 컬럼을 검색하는 질의이다.

FROM절상의 서브쿼리(INLINE VIEW) : FROM절상에 오는 서브쿼리로 VIEW처럼 작용 한다.

상관관계 서브 쿼리 : 바깥쪽 쿼리의 컬럼 중의 하나가 안쪽 서브쿼리의 조건에 이용되는 처리 방식 이다.

   

  • 단일 행(Single-Row) 서브쿼리

- 오직 한개의 행(값)을 반환.

- 단일 행 연산자(=,>, >=, <, <=, <>, !=) 만 사용.

   

SQL> SELECT ename,job
FROM emp
WHERE job = (SELECT job
FROM emp
WHERE empno = 7369);

  

-- 위의 서브쿼리를 실행 시키면 아래의 그림처럼,
-- empno가 7369인 job을 먼저 검색하고, job이 'CLERK'인
-- 사원의 이름과 직업을 반환 한다.

   

   

  •    

  • 다중 행(Multiple-Row) 서브쿼리

- 하나 이상의 행을 반환하는 서브쿼리를 다중 행 서브쿼리라고 한다.

- 복수 행 연산자(IN, NOT IN, ANY, ALL, EXISTS)를 사용 할 수 있다.

   

  • IN 연산자의 사용 예제


-- 부서별로 가장 급여를 많이 받는 사원의 정보를 출력하는 예제
SQL> SELECT empno,ename,sal,deptno
FROM emp
WHERE sal IN (SELECT MAX(sal)
FROM emp
GROUP BY deptno);

  

   

select max(sal)

from emp group by deptno

   

   

  

select empno, ename, sal, deptno

from emp

where sal in (2850,3000,5000)

   

   

   

   

   

SELECT empno,ename,sal,deptno
FROM emp
WHERE sal IN (SELECT MAX(sal)
FROM emp
GROUP BY deptno);

EMPNO ENAME SAL DEPTNO
---------- -------- --------- ---------
7698 BLAKE 2850 30
7788 SCOTT 3000 20
7902 FORD 3000 20
7839 KING 5000 10

   

  • ANY 연산자의 사용 예제
    • ANY 연산자는 서브쿼리의 결과값 중 어느 하나의 값이라도 만족이 되면 결과값을 반환 한다.

 

SQL> SELECT ename, sal
FROM emp
WHERE deptno != 20
AND sal > ANY (SELECT sal
FROM emp
WHERE job='SALESMAN');

  

 

   

SELECT sal

FROM emp

WHERE job='SALESMAN'

   

   

SELECT ename, sal

FROM emp

WHERE deptno != 20

AND sal > ANY ( 1600,1250,1250,1500);

   

   

   

SELECT ename, sal
FROM emp
WHERE deptno != 20
AND sal > ANY (SELECT sal
FROM emp
WHERE job='SALESMAN');


ENAME SAL
---------- ----------
ALLEN 1600
BLAKE 2850
CLARK 2450
...

   

  • ALL 연산자의 사용 예제
    • ALL 연산자는 서브쿼리의 결과값 중 모든 결과 값이 만족 되야 만 결과값을 반환 한다.


SQL> SELECT ename, sal
FROM emp
WHERE deptno != 20
AND sal > ALL (SELECT sal
FROM emp
WHERE job='SALESMAN');

  

 

SELECT sal

FROM emp

WHERE job='SALESMAN'

   

 

SELECT ename, sal

FROM emp

WHERE deptno != 20

AND sal > ALL ( 1600,1250,1250,1500);

   

 

   

SELECT ename, sal
FROM emp
WHERE deptno != 20
AND sal > ALL (SELECT sal
FROM emp
WHERE job='SALESMAN');

   

ENAME SAL
---------- ----------
BLAKE 2850
CLARK 2450
KING 5000

 

   

  • EXISTS 연산자의 사용 예제
    • EXISTS 연산자를 사용하면 서브쿼리의 데이터가 존재하는가의 여부를 먼저 따져 존재하는 값 들만을 결과로 반환해 준다.서브쿼리에서 적어도 한 개의 행을 반환하면 논리식은 참이고 그렇지 않으면 거짓 이다.

-- 사원을 관리할 수 있는 사원의 정보 조회 예제 (상관관계 서브쿼리)


SQL> SELECT empno, ename, sal
FROM emp e
WHERE EXISTS (SELECT empno
FROM emp
WHERE e.empno = mgr)

  

   

   

EMPNO ENAME SAL
---------- -------- --------
7566 JONES 2975
7698 BLAKE 2850
7782 CLARK 2450
...

   

  • 다중 열(Multiple-Column) 서브쿼리
    • 다중 열 서브쿼리란 서브쿼리의 결과 값이 두 개 이상의 컬럼을 반환하는 서브쿼리 이다.

   

  • Pairwise(쌍비교) Subquery
    • 서브쿼리가 한 번 실행되면서 모든 조건을 검색해서 주 쿼리로 넘겨 준다.


SQL> SELECT empno, sal, deptno
FROM emp
WHERE (sal, deptno) IN ( SELECT sal, deptno
FROM emp
WHERE deptno = 30
AND comm is NOT NULL );

  

 

SELECT sal, deptno

FROM emp

WHERE deptno = 30

AND comm is NOT NULL

   

SELECT empno, sal, deptno

FROM emp

WHERE (sal, deptno) IN ( (1600, 30),(1250,30),(1250,30),(1500, 30));

   

   

 

   

   

SELECT empno, sal, deptno
FROM emp
WHERE (sal, deptno) IN ( SELECT sal, deptno
FROM emp
WHERE deptno = 30
AND comm is NOT NULL );

 


EMPNO SAL DEPTNO
---------- ---------- ----------
7521 1250 30
7654 1250 30
7844 1500 30
7499 1600 30

   

   

   

  • Nonpairwise(비쌍비교) Subquery
    • 서브쿼리가 여러 조건별로 사용 되어서 결과 값을 주 쿼리로 넘겨 준다.


SQL> SELECT empno, sal, deptno
FROM emp
WHERE sal IN ( SELECT sal
FROM emp
WHERE deptno = 30
AND comm is NOT NULL )
AND deptno IN ( SELECT deptno
FROM emp
WHERE deptno = 30
AND comm is NOT NULL );

  

   

   

SELECT sal

FROM emp

WHERE deptno = 30

AND comm is NOT NULL

   

   

   

SELECT deptno

FROM emp

WHERE deptno = 30

AND comm is NOT NULL

   

   

   

SELECT empno, sal, deptno

FROM emp

WHERE sal IN ( 1600,1250,1250, 1500 )

AND deptno IN ( 30, 30, 30, 30 );

   

   

 

   

   

SELECT empno, sal, deptno
FROM emp
WHERE sal IN ( SELECT sal
FROM emp
WHERE deptno = 30
AND comm is NOT NULL )
AND deptno IN ( SELECT deptno
FROM emp
WHERE deptno = 30
AND comm is NOT NULL );

   

EMPNO SAL DEPTNO
---------- ---------- ----------
7521 1250 30
7654 1250 30
7844 1500 30
7499 1600 30

   

   

  • Null Values in a Subquery
    • 서브쿼리에서 NULL 값이 반환 되면 주 쿼리 에서는 어떠한 행도 반환되지 않는다.

   

  • FROM절상의 서브쿼리(INLINE VIEW)
    • INLINE VIEW란 FROM절 상에 오는 서브쿼리로 VIEW처럼 작용 한다.
      • View
        • 실제테이블을 참고로 가상적인 테이블을 제공, 복수의 테이블에서 데이터를 검색
          • 데이터 접근의 권한
          • 복잡한 쿼리의 간소화
          • 데이터의 독립성 확보
          • 동일 데이터를 서로 다른 뷰에게 제공

             


-- 급여가 부서번호 20의 평균 급여보다 크고, 사원을 관리하는 사원으로서
-- 부서번호 20에 속하지 않은 사원의 정보를 조회하는 SQL 문장이다.
SQL> SELECT b.empno,b.ename,b.job,b.sal, b.deptno
FROM (SELECT empno
FROM emp
WHERE sal >(SELECT AVG(sal)
FROM emp
WHERE deptno = 20)) a, emp b
WHERE a.empno = b.empno
AND b.mgr is NOT NULL
AND b.deptno != 20

  

   

SELECT AVG(sal)

FROM emp

WHERE deptno = 20

   

   

   

SELECT empno

FROM emp

WHERE sal >2175

   

SELECT b.empno,b.ename,b.job,b.sal, b.deptno

FROM (SELECT empno

FROM emp

WHERE sal >2175) a, emp b

WHERE a.empno = b.empno

AND b.mgr is NOT NULL

AND b.deptno != 20

   

  

 

   

   

SELECT b.empno,b.ename,b.job,b.sal, b.deptno
FROM (SELECT empno
FROM emp
WHERE sal >(SELECT AVG(sal)
FROM emp
WHERE deptno = 20)) a, emp b
WHERE a.empno = b.empno
AND b.mgr is NOT NULL
AND b.deptno != 20

   


EMPNO ENAME JOB SAL DEPTNO
---------- ---------- --------- ---------- ----------
7698 BLAKE MANAGER 2850 30
7782 CLARK MANAGER 2450 10

   

   

  • 상관관계 서브쿼리
    • 상관관계 서브쿼리란 바깥쪽 쿼리의 컬럼 중의 하나가 안쪽 서브쿼리의 조건에 이용되는 처리 방식 이며, 이는 주 쿼리에서 서브쿼리를 참조하고 이 값을 다시 주 쿼리로 반환 한다는 것이다.


-- 사원을 관리할 수 있는 사원의 평균급여보다 급여를 많이 받는 사원의 정보를 출력
SQL> SELECT empno, ename, sal
FROM emp e
WHERE sal > (SELECT AVG(sal) sal
FROM emp
WHERE e.empno = mgr)

  

 

바깥쪽 쿼리

   

SELECT empno, ename, sal

FROM emp e

   

   

e.empno

안쪽 쿼리

   

e.empno = mgr

 

 

   

   

   

SELECT empno, ename, sal
FROM emp e
WHERE sal > (SELECT AVG(sal) sal
FROM emp
WHERE e.empno = mgr

   

EMPNO ENAME SAL
---------- ---------- ----------
7698 BLAKE 2850
7782 CLARK 2450
7788 SCOTT 3000
7839 KING 5000
7902 FORD 3000

   

  • 집합 쿼리(UNION, INTERSECT, MINUS)
    • 집합 연산자를 사용시 집합을 구성할 컬럼의 데이터 타입이 동일해야 한다.
      •  UNION : 합집합
      •  UNION ALL : 중복 데이터를 다 포함하는 합집합
      •  INTERSECT : 교집합
      •  MINUS : 차집합
  • UNION
    • UNION은 두 테이블의 결합을 나타내며, 결합시키는 두 테이블의 중복되지 않은 값들을 반환 한다.

SQL> SELECT deptno FROM emp
UNION
SELECT deptno FROM dept;

  

 

SELECT deptno FROM emp

   

   

   

   

   

   

   

   

   

UNION

SELECT deptno FROM dept

   

   

   

   

   

   

   

  

   

   

   

SELECT deptno FROM emp
UNION
SELECT deptno FROM dept;

   

DEPTNO
----------
10
20
30
40

  • UNION ALL
    • UNION과 같으나 두 테이블의 중복되는 값 까지 반환 한다.

SQL> SELECT deptno FROM emp
UNION ALL
SELECT deptno FROM dept;

  

 

 

SELECT deptno FROM emp

   

   

   

   

   

   

   

   

   

UNION ALL

SELECT deptno FROM dept

   

   

   

   

   

   

   

  

   

   

   

SELECT deptno FROM emp
UNION ALL
SELECT deptno FROM dept;

   

DEPTNO
---------
20
30
30
20
30
30
10
20
10

30

. ….

   

  • INTERSECT
    • INTERSECT는 두 행의 집합중 공통된 행을 반환 한다.

SQL> SELECT deptno FROM emp
INTERSECT
SELECT deptno FROM dept;

  

 

 

SELECT deptno FROM emp

   

   

   

   

   

   

   

   

   

INTERSECT

SELECT deptno FROM dept

   

   

   

   

   

   

   

  

   

   

SELECT deptno FROM emp
INTERSECT
SELECT deptno FROM dept;


DEPTNO
----------
10
20
30

 

  • MINUS
    • MINUS는 첫 번째 SELECT문에 의해 반환되는 행 중에서 두 번째 SELECT문에 의해 반환되는 행에 존재하지 않는 행들을 반환 한다.


SQL> SELECT deptno FROM dept
MINUS
SELECT deptno FROM emp;

  

 

 

SELECT deptno FROM dept

   

   

   

   

   

   

  

   

   

   

   

   

   

   

   

MINUS

SELECT deptno FROM emp

   

   

  

   

   

   

SELECT deptno FROM dept
MINUS
SELECT deptno FROM emp;

   

DEPTNO
----------
40

   

   

   

  • 스칼라 서브쿼리
    • 스칼라 서브쿼리란 Select-List에서 서브쿼리가 사용될 때 이를 스칼라 서브 쿼리라고 함.
    • 특징
      • 하나의 레코드만 리턴이 가능하며, 두 개 이상의 레코드는 리턴할 수 없다.
      • 일치하는 데이터가 없더라도 NULL값을 리턴할 수 있다. 이는 원래 그룹함수의 특징 중에 하나인데 스칼라 서브쿼리 또한 이 특징을 가지고 있다.

           

-- 1. 그룹함수 사용 안할 때는 리턴하는 값이 없음
SELECT 1
FROM DEPT
WHERE 1 = 2
;

  


no rows selected

   

   

   

-- 2. 그룹함수를 사용하면 값을 리턴함
SELECT MIN(DEPTNO)
FROM DEPT
WHERE 1 = 2
;

  


MIN(DEPTNO)
-----------

1 row selected.

   

   

   

-- 3. 스칼라 서브쿼리 테스트(일치하는 값이 없을 경우 NULL 리턴함)
-- EMP:DEPT = M:1 관계에서 M 대상을 올리다보니 GROUP BY 을 추가함
SELECT D.DEPTNO,
(SELECT MIN(EMPNO)
FROM EMP
WHERE DEPTNO = D.DEPTNO) EMPNO
FROM DEPT D
ORDER BY D.DEPTNO
;

  

   

   

화면 캡처: 2011-12-28 오후 1:13

   

   

   

  • 스칼라 서브쿼리와 Outer 조인 관계
    • 위와 같이 스칼라 서브쿼리는 일치하지 않더라도 NULL를 리턴하므로 Outer 조인과 같은 형태이며,
      이는 스칼라 서브쿼리와 Outer 조인은 서로 변형이 가능하다는 것을 알 수 있다.

         

SELECT D.DEPTNO,
E.EMPNO
FROM DEPT D,
(SELECT DEPTNO,
MIN(EMPNO) EMPNO
FROM EMP
GROUP BY DEPTNO) E
WHERE D.DEPTNO = E.DEPTNO(+)
ORDER BY D.DEPTNO


;

   

   

   

화면 캡처: 2011-12-28 오후 1:13

   

   

   

<참고문헌>

Oracle Database 11g : Adminstration Workshop

Oracle Database 10g Documentation Library - councepts

원본 위치 <http://www.oracleclub.com>

원본 위치 <http://www.oracleclub.com/lecture/1501>

원본 위치 <http://cong4u.tistory.com/120>

원본 위치 <http://www.gurubee.net/pages/viewpage.action?pageId=4948016>

블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,

Oracle HINT(기초)

1. IT Story/DB 2012. 2. 29. 21:47

오라클 HINT

  • 쿼리문이 실행될 때 기본적으로 DB내에 존재하는 옵티마이저가 쿼리를 분석한 뒤 가장 좋은 계획을 세워서 쿼리를 실행하고 결과를 반환한다.

    모든 사항을 고려하여 자동으로 결정하므로 편하지만, 100% 믿을 수는 없다.

    그래서 옵티마이저에게 맡기지 않고 쿼리를 작성한 사람이 직접, 원하는 대로 실행방법을 지정하여 실행하는 방법이 오라클 HINT이다.

   

-프로그램이 완벽하지 않기 때문에 세부적이고, 중요한 처리를 사람이 직접 수정하기 위해 사용.

   

  • 힌트를 사용하려면 두가지 방법이 있다.

   

1.   /*+   힌트    */

2.   --+   힌트

   

  • 두 가지의 방식은 실제 힌트문장에는 차이가 없고, 서술하는 방식의 차이이다, 1번은 여러줄에 걸쳐쓸 수 있는 반면 2번은 한 줄에만 적용이 된다.  개발할때 주석도 한줄주석 여러줄 주석 그런거 처럼…

   

Hints from Optimization Approaches and Goals

  

  

HINT

내용

사용법

ALL_ROWS

cost-based optimizer에서 전체 응답시간이 가장 적은 plan 선택

/*+ ALL_ROWS */

FIRST_ROWS(n)

: cost-based optimizer에서 첫번째 row가 가장 빨리 나오는 plan으로 선택

/*+ FIRST_ROWS(10) */

/*+ FIRST_ROWS(n) */

CHOOSE

통계정보의 유무에 따라 RBO/CBO 가 선택됨

/*+ CHOOSE */

RULE

rule-based optimization로 plan 작성

/*+ RULE */

   

<TEST>

   

select distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:09

   

  1. /*+ ALL_ROWS */

       

select /*+ All_ROWS(10) */ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:09

   

   

   

  1. /*+ FIRST_ROWS(10) */

       

select /*+ FiRST_ROWS(10) */ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:10

   

   

   

  1. /*+ CHOOSE */

       

select /*+ CHOOSE */ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:10

   

   

  1. /*+ RULE */

       

select /*+ RULE */ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:12

   

Hints for Query Transformations

  

  

HINT

내용

사용법

USE_CONCAT

: IN 또는 OR 연산자가 있을 경우 CONCATENATION 을 사용하도록 한다

in절을 concatenation access operation으로 수행

/*+ USE_CONCAT */

USE_EXPAND

in절을 concatenation access operation으로 수행 못하게 함

  

NO_EXPAND

  

  

REWRITE

query rewrite 수행

  

EXPAND_GSET_TO_UNION

  

  

NOREWRITE

query rewrite 를  수행 못함

  

MERGE

view merging 수행

  

NO_MERGE

view merging 수행 못하게 함

  

STAR_TRANSFORMATION

  

  

FACT

  

  

NO_FACT

  

  

   

Hints from Access Paths

  

  

HINT

내용

사용법

FULL

TABLE FULL SCAN 을 하도록 유도

FULL SCAN

  

/*+ FULL(A) don't use the index on A.table */

FULL(TALBE명)

ROWID

  

  

CLUSTER

Cluster Scan을 선택하도록 지정한다. 따라서 clustered object들에만 적용 됩니다.

/*+CLUSTER(table name)*/

HASH

  

  

INDEX

( = INDEX_ASC) : 지정한 인덱스를 사용하여 ACCESS PLAN을 작성하도록 유도

INDEX를 순차적으로 스캔

  

/*+ INDEX(patients name_index) */,

INDEX(TABLE명, INDEX명)

INDEX_ASC

지정된 index를 오름차순으로 쓰게끔 지정 합니다. Default로 Index Scan은 오름차순.

   

  

  

INDEX_JOIN

  

  

INDEX_DESC

INDEX_DESC : 지정한 인덱스를 사용하여 ACCESS PLAN을 작성하도록 유도

(인덱스를 맨뒤에서부터 SCAN 하도록 한다)

INDEX를 역순으로 스캔

/*+ INDEX_DESC(patients name_index) */

INDEX_DESC(TABLE명, INDEX명)

  

INDEX_FFS

INDEX FAST FULL SCAN

INDEX_FFS(TABLE명, INDEX명)

AND_EQUAL

NDEX MERGE 수행

AND_EQUALS(INDEX_NAME, INDEX_NAME)

   

<Test1>

   

select d.department_id, d.department_name, COUNT(*) from departments d, employees e where d.department_id = e.department_id group by d.department_id, d.department_name having count(*) <3;

Full(A)

   

   

   

화면 캡처: 2011-12-27 오전 11:16

   

   

  • /*+ FULL(A) don't use the index on A.table */

       

select /*+ FULL(e) don't use the index on e*/ distinct d.department_id, d.department_name, COUNT(*) from departments d, employees e where d.department_id = e.department_id group by d.department_id, d.department_name having count(*) <3;

  

   

   

화면 캡처: 2011-12-27 오전 11:19

   

   

<Test2>

   

select distinct job_id from employees where department_id in (10,20);

  

   

   

   

화면 캡처: 2011-12-27 오전 11:26

  

  • /*+ INDEX(patients name_index) */

       

select /*+ INDEX(employees EMP_JOB_IX)*/ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:28

   

select /*+ INDEX(employees EMP_EMP_ID_PK)*/ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:28

   

   

  • /*+ INDEX_ASC(patients name_index) */

       

    선수되어있던 인덱스를 이용해서 순차적으로 검색?

       

select /*+ INDEX_ASC(employees EMP_EMP_ID_PK)*/ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:31

   

  • /*+ INDEXJOIN(patients name_index) */

       

select /*+ INDEX_JOIN(employees EMP_EMP_ID_PK)*/ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:32

   

   

  • /*+ INDEX_DESC(patients name_index) */

       

select /*+ INDEX_DESC(employees EMP_EMP_ID_PK)*/ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:33

   

   

   

  • /*+ INDEX_FFS(patients name_index) */

       

select /*+ INDEX_FFS(employees EMP_EMP_ID_PK)*/ distinct job_id from employees where department_id in (10,20);

  

   

   

화면 캡처: 2011-12-27 오전 11:33

   

Hints from join orders

  

  

HINT

내용

사용법

ORDERED

FROM 절에 있는 테이블들의 JOIN 순서를 지정함

/*+ ORDERED */

STAR

  

  

DRIVING

해당 테이블을 먼저 DRIVING- driving(table)

  

   

Hints for join Operations

  

  

HINT

내용

사용법

USE_NL

지정한 테이블에 대해 NESTED LOOP 조인이 일어나도록 지정함

NESTED LOOP JOIN

/*+ ORDERED USE_NL() to get first row faster */

USE_NL(TABLE1, TABLE2)

  

USE_MERGE

지정한 테이블에 대해 SORT MERGE 조인이 일어나도록 지정함

SORT MERGE JOIN

  

/*+USE_MERGE(emp dept)*/

USE_MERGE(TABBLE1, TABLE2)

USE_HASH

지정한 테이블에 대해 HASH 조인이 일어나도록 지정함

HASH JOIN

  

/*+USE_HASH(emp dept)*/

USE_HASH(TABLE1, TABLE2)

  

DRIVING_SITE

  

  

LEADING

  

  

HASH_AJ, HASH_SJ

HASH ANTIJOIN

HASH SEMIJOIN

HASH_AJ(TABLE1, TABLE2)

HASH_SJ(TABLE1, TABLE2)

MERGE_AJ, MERGE_SJ

SORT MERGE ANTIJOIN

SORT MERGE SEMIJOIN

MERGE_AJ(TABLE1, TABLE2)

MERGE_SJ(TABLE1, TABLE2)

NL_AJ, NL_SJ

NESTED LOOP ANTI JOIN

NESTED LOOP SEMIJOIN

NL_AJ(TABLE1, TABLE2)

NL_SJ(TABLE1, TABLE2)

   

<Test>

   

select * from employees, departments where employees.department_id = departments.department_id;

  

   

   

   

화면 캡처: 2011-12-27 오전 11:40

   

   

  1. /*+ USE_NL(TABBLE1, TABLE2) */

       

select /*+ USE_NL(employees, departments) */ * from employees, departments where employees.department_id = departments.department_id;

  

   

   

화면 캡처: 2011-12-27 오전 11:40

   

   

  1. /*+ USE_MERGE(TABBLE1, TABLE2) */

       

select /*+ USE_MERGE(employees, departments) */ * from employees, departments where employees.department_id = departments.department_id;

  

   

   

화면 캡처: 2011-12-27 오전 11:40

   

   

  1. /*+ USE_HASH(TABBLE1, TABLE2) */

       

select /*+ USE_HASH(employees, departments) */ * from employees, departments where employees.department_id = departments.department_id;

  

   

   

화면 캡처: 2011-12-27 오전 11:40

   

Hints for Parallel Execution

  

  

HINT

내용

사용법

Parallel        

select, insert 시 여러 개의 프로세스로 수행- parallel(table, 개수)

  

NOPARALLEL

  

  

PQ_DISTRIBUTE

  

  

PARALLEL_INDEX

NDEX PARALLEL SCAN

PARALLEL_INDEX(TABLE명,INDEX명)

NOPARALLEL_INDEX

NDEX PARALLEL SCAN 제한

NOPARALLEL_INDEX(TABLE명,INDEX명)

   

DEGREE의 의미 및 결정

  •   Parallel Query에서 degree란 하나의 operation 수행에 대한 server process의 개수 입니다. 이러한 degree 결정에 영향을 주는 요인들에는 다음과 같은 것들이 있습니다.

    (1) system의 CPU 갯수

    (2) system의 maximum process 갯수

    (3) table이 striping되어 있는 경우, 그 table이 걸쳐있는 disk의 갯수

    (4) data의 위치 (즉, memory에 cache되어 있는지, disk에 있는지)

    (5) query의 형태 (예를 들어 sorts 혹은 full table scan)

  •   한 사용자만이 parallel query를 사용하는 경우, sorting이 많이 필요한 작업과 같은 CPU-bound 작업의 경우는 CPU 갯수의 1 ~ 2배의 degree가 적당하며, sorting보다는 table scan과 같은 I/O bound 작업의 경우는 disk drive 갯수의 1 ~ 2배가 적당합니다.
  •   동시에 수행되는 parallel query가 많은 경우에는 위의 각 사용자의 degree를 줄이거나 동시에 사용하는 사용자 수를 줄여야 합니다.

   

Additional Hints

  

  

HINT

내용

사용법

APPEND

insert 시 direct loading

/*+ APPEND */

NOAPPEND

  

  

CACHE

데이터를 메모리에 caching

  

NOCACHE

데이터를 메모리에 caching하지 않음

  

UNNEST

  

  

NO_UNNEST

  

  

PUSH_PRED

  

  

NO_PUSH_PRED

  

  

PUSH_SUBQ

subquery를 먼저 수행

  

NO_PUSH_SUBQ

  

  

ORDERED_PREDICATES

  

  

CURSOR_SHARING_EXACT

  

  

DYNAMIC_SAMPLING

  

  

   

   

조인 순서 조정을 위한 힌트

힌트는 다수의 테이블을 조인하는 경우에 조인 순서에 혼선이 있을 적용하는 것이 가장 일반적이다.

Sort Merge 조인 이나 해쉬조인에서는 적은 테이블을 먼저 처리하도록 유도할 사용하는 것이 좋다.

ORDERED

FROM절에 기술된 테이블 순서대로 조인을 수행하도록 유도한다.

만약 LEADING 힌트와 함께 사용하면 LEADING 힌트는 무시된다.

) SELECT /*+ ORDERED */ ...
FROM TAB1, TAB2, TAB3
WHERE ....

ORDERED 힌트는 액세스 순서만 제시할 뿐이고, 조인 방법 과는 무관하기 때문에 조인방법을 유도하기 위한 USE_NL, USE_MERGE등의 힌트와 함께 사용하는 것이 일반적이다

) SELECT /*+ ORDERED USE_NL(A B C) */.........
FROM TAB1 a, TAB2 b, TAB3 c
WHERE ........

LEADING

FROM절에 기술한 테이블의 순서와 상관없이 조인 순서를 제어하는 힌트로서 ORDERED 힌트와는 달리 FROM절을 변경 필요 없이 사용할 있다.

ORDERED 힌트와 함께 사용되면 무시된다.

) SELECT /*+ LEADING(b c) */......
FROM CUST a, ORDER_DETAIL b, ITEM c
WHERE a.cust_no = b.cust_no
         AND b.item_no = c.item_no
         AND ....

    

   

   

<참고문헌>

Oracle Database 11g : Adminstration Workshop

Oracle Database 10g Documentation Library - councepts

원본 위치 <http://www.oracleclub.com>

원본 위치 <http://www.oracleclub.com/lecture/1260>

원본 위치 <http://blog.naver.com/PostView.nhn?blogId=comele&logNo=70069313846&beginTime=0&jumpingVid=&from=search&redirect=Log&widgetTypeCall=true&topReferer=http%3A%2F%2Fsearch.naver.com%2Fsearch.naver%3Fsm%3Dtab_hty.top%26where%3Dnexearch%26ie%3Dutf8%26query%3D%25EC%2598%25A4%25EB%259D%25BC%25ED%2581%25B4%2B%25ED%259E%258C%25ED%258A%25B8%26x%3D0%26y%3D0>

원본 위치 <http://blog.naver.com/PostView.nhn?blogId=myshyz&logNo=50125858009&beginTime=0&jumpingVid=&from=search&redirect=Log&widgetTypeCall=true&topReferer=http%3A%2F%2Fsearch.naver.com%2Fsearch.naver%3Fwhere%3Dnexearch%26query%3DOracle%2BHint%26x%3D21%26y%3D23%26sm%3Dtop_hty%26fbm%3D1%26ie%3Dutf8>


블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,


Driving Table 과 JOIN

   

   

  • Driving Table
    • 가장먼저 Access되는 Table 로 Join 문장을 구성 시에 중요한 요소
    • Hint 를 사용하여 Triving Table 을 지정 가능
    • Optimizer Mode 가 Cost Base 일 경우에는 통계정보가 우선하나 일반적으로 FROM 절에서 앞 Table 이 Driving Table 이 됨.
    • Rule Base 일 경우에는 동일 조건일 때 FROM 절에서 뒤 Table 을 Optimizer 가 Access 하게 됨.

         

         

      화면 캡처: 2011-12-29 오후 5:24

         

  • Join 의 원리
    • Join 이란 테이블간에 물리적 관계가 없어도 논리적 관계만으로 원하는 정보를 서로 연결하여 참조할 경우에 사용
    • Join 시 수행속도를 향상하려면 Access 횟수를 줄이는 것이 기본이자 원리
    • 둘 이상의 테이블을 연결하여 데이터를 검색하는 방법 이다.
    • 보통 둘 이상의 행들의 공통된 값 Primary Key 및 Foreign Key 값을 사용하여 조인 한다.
    • 그러므로 두 개의 테이블을 SELECT문장 안에서 조인 하려면 적어도 하나의 컬럼이 그 두 테이블 사이에서 공유 되어야 한다.

       

  1. Join 의 종류

   

  1. Equi, non_Equi, self Join

       

  • Cartesian Product(카티션 곱)

    - 검색하고자 했던 데이터뿐 아니라 조인에 사용된 테이블들의 모든 데이터가 반환 되는 현상

       

    - Cartesian Product는 다음과 같은 경우에 발생 한다.

    * 조인 조건을 정의하지 않았을 경우

    * 조인 조건이 잘못된 경우

    * 첫 번째 테이블의 모든 행들이 두 번째 테이블의 모든 행과 조인이 되는 경우

    * 테이블의 개수가 N이라면 Cartesian Product를 피하기 위해서는 적어도 N-1개의 등가 조건을 SELECT 문안에 포함시켜서 다른 테이블 안에 있는 각 테이블의 컬럼이 적어도 한번은 참조되도록 해야 한다.

  1. Equi Join

    - 조건절 Equality Condition(=)에 의하여 조인이 이루 진다.

    - Equi join의 성능을 높이기 위해서는 Index 기능을 사용하는 것이 좋다.


 

-- WHERE 절에 조인 조건을 작성한다.
SQL>
SELECT e.ename, d.dname
FROM emp e , dept d
WHERE e.deptno = d.deptno;

   

   

화면 캡처: 2011-12-28 오후 5:25

   

   

화면 캡처: 2011-12-28 오후 5:27

   

   

  1. Non-Equi Join
  • - Non-equi Join은 테이블의 어떤 column도 Join할 테이블의 column에 일치하지 않을 때 사용하고, 조인조건은 동등( = )이외의 연산자를 갖는다.
  • BETWEEN AND, IS NULL, IS NOT NULL, IN, NOT IN

  

-- Non-Equi Join 예제
SQL>

SELECT e.ename,e.sal,s.grade
FROM emp e, salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal;

   

   

   

화면 캡처: 2011-12-28 오후 5:26

   

   

화면 캡처: 2011-12-28 오후 5:28

   

   

  1. Self Join
  • - Equi Join과 같으나 하나의 테이블에서 조인이 일어나는 것이 다르다.
  • - 같은 테이블에 대해 두 개의 alias를 사용하여 FROM절에 두 개의 테이블을 사용하는 것 처럼 조인한다.

 

-- 사원의 매니저명을 조회하는 Self Join 예제
SQL>
SELECT e.ename, a.ename "Manager"
FROM emp e, emp a
WHERE e.empno = a.mgr;

   

   

화면 캡처: 2011-12-28 오후 5:29

   

   

   

화면 캡처: 2011-12-28 오후 5:29

   

  1. Nested Loop Join

       

    - Driving Table 의 처리범위에 있는 각각의 로우들이 순차적으로 수행될 뿐 아니라 테이블간의 연결도 순차적임.

    - 선행적 특징을 갖으며, 먼저 엑세스되는 테이블의 처림범위에 의해 처리량이 결정됨.

       

  • Nested Loop Join 의 원리

       

 SQL 문

 SELECT A.COL1, B.COL2

    FORM TAB1 B, TAB2 A

  WHERE B.KEY2 = A.KEY1

       AND A.KEY = 'AA'

       AND A.COL1 = '11'

       AND B.COL2 = '22';

   

   

 INDEX 정보

테이블 명 : 인덱스명  : 컬럼구성

TAB2 A    : TAB2_PK : KEY1

TAB1 B    : TAB1_PK : KEY2

   

   

실행계획

   

 1. INDEX TAB2PK ACCESS 후 ROWID 추출

 2. 테이블 TAB2 ACCESS

 3. NESTED LOOP JOIN 으로 INDEX TAB1_PK를 ACCESS

 4. ROWID 로 테이블 TAB1 을 읽음

   

  

   

  • Nested Loop Join 의 특징

       

 순차적

 Driving Table 의 처리범위에 있는 각각의 로우들이 순차적으로 수행될 뿐 아니라 테이블간의 연결도 순차적임

 선행적

 먼저 엑세스되는 테이블의 처림범위에 의해 처리량이 결정

 종속적

 나주엥 처리도는 테이블은 앞서 처리된 값을 받아 엑세스함. 즉 값을 받아서 처리범위가 정해짐

 RANDOM ACCESS

 Driving Table 의 인덱스 엑세스는 첫 번째 로우만 Random Access 이고, 나머지는 Scan, 연결작업은 Random Access

 선택적

 연결되는 방향에 따라 사용되는 INDEX 들이 달라질 수 있음.

 연결고리중요, 방향성

 연결고리의 인덱스 유무에 따라 엑세스 바향 및 수행 속도에 차이 발생

 부분범위처리가능

 연결작업 수행 후 Check 되는 조건으로 부분범위처리를 하는 경우 조건의 범위가 넓거나 없다면 더 빨라짐

   

  • Nested Loop Join 의 사용

       

 부분범위처리를 하는 경우

- 전체가아닌 부분범위 처리하는 경우에 유리

 Join 되는 테이블이 상호의존적인 경우

- Join 되는 어느 한쪽이 상대방 테이블에서 추출된 결과를 받아서 처리량을 줄일 수 있을 경우 유리

- Driving Table 의 처리가 많거나 연결 테이블의 Random Access 량이 많을 경우 Sort/Merge Join이 유리

 처리량이 적은 경우

- Random Access 를 많이 하므로 On-Line 애플리케이션 같이 처리량이 적은 경우에 유리

 Driving Table 의 선택이 관건

- 어느 테이블이 먼저 Access 되는가가 수행속도에 큰 영향을 미침

   

   

  1. Sort Merge Join

       

  • Sort Merge Join 의 원리

    - 일반적으로 Batch 나 DW작업 처리시 사용하며 전체적인 자료를 처리하는 경우에 주로 사용

    - Eqil-join 에 대해서만 사용가능

    - 사용시 Optimizer 에 HINT(USE_MERGE)를 사용하여 처리

    - 각각의 테이블에 대하여 Sort 처리 후 Merge 를 하는 Join

       

   

 SQL 문

 SELECT /** USE_MERGE(B A) */ A.COL1, B.COL2

    FORM TAB1 B, TAB2 A

  WHERE B.KEY2 = B.KEY1

       AND A.KEY = 'AA'

       AND A.COL1 = '11'

       AND B.COL2 = '22';

   

 INDEX 정보

테이블 명 : 인덱스명  : 컬럼구성

TAB2 A    : TAB2_PK : KEY1

TAB1 B    : TAB1_PK : KEY2

   

실행계획

   

 1. INDEX TAB2PK ACCESS 후 ROWID 추출

 2. 테이블 TAB2 ACCESS 한 결과를 SORT

 3. 테이블 TAB1 을 FTS(Full Table Scan) 한 후 SORT

 4. 두 테이블 결과를 MERGE

   

   

  • Sort Merge Join 의 특징

       

동시적

각각의 테이블이 자신의 처리범위를 엑세스하여 정렬해 둠

독립적

각 테이블은 다른 테이블에서 어떤 상수값도 제공받지 않고 주어진 상수값에 의해서만 범위를

전체범위처리

부분범위를 사용할 수 없음

Scan방식

자신의 처리범위를 줄이기 위해 index 를 사용하는 경우에만 Random Access 하고 Merge 작업은 Scanq 방식사용

선택적

연결고리가 되는 컬럼은 인덱스를 사용하지 않음

무방향성

Join 의 방향과 무관

   

  • Sort Merge Join 의 사용

       

전체범위처리를 하는 경우

- Sort/Merge Join 은 주로 부분이 아닌 전체범위를 처리하는 경우에 유리

Hash Join이 수행 하지 못하는 EQUI-JOIN 일 때 주로 사용, 그 외의 경우는 모두 Hash Join을 사용한다.

Join 되는 테이블이 상호독립적인 경우

- 상대방 테이블에서 어떤 상수값을 받지 않고도 처리범위를 줄일 수 있을 경우 유리함

- 상수값을 받아 줄여진 범위가 30%이상이면 Sort/Merge Join 이 유리

처리량이 많은 경우

- Random Access 를 하지 않으므로 전체범위처리에 유리

효과적인 인덱스 구성이 관건

- 자신의 처리범위를 어떻게 줄이느냐가 관건이므로 효과적인 인덱스 구성이 중요

   

   

   

   

  1. Hash Join

       

    - Oracle8 Server 는 Cost-Based 옵티마이저를 사용하는 경우만 Hash Join 을 고려

    - Equi-Join 에 대해서만 사용가능

    - 일반적으로 HINT(USE_HASH) 를 사용하여 처리

    - HASH FUNCTION 을 이용해서 메모리와 CPU를 많이 사용해서 대용량 데이터를 처리할 경우에 사용

       

  • Hash Join 의 원리

       

 SQL 문

 SELECT /** USE_HASH(B A) */ A.COL1, B.COL2

    FORM TAB1 B, TAB2 A

  WHERE B.KEY2 = B.KEY1

       AND A.KEY = 'AA'

       AND A.COL1 = '11'

       AND B.COL2 = '22';

   

   

 INDEX 정보

테이블 명 : 인덱스명  : 컬럼구성

TAB2 A    : TAB2_PK : KEY1

TAB1 B    : TAB1_PK : KEY2

   

   

실행계획

   

  

 1. INDEX TAB2PK ACCESS 후 ROWID 로 테이블 TAB2 ACCESS

 2. 테이블 TAB1 을 FTS(Full Table Scan)

 3. 두 테이블 결과를 HASH JOIN

   

  

   

  • Hash Join 의 특징

       

선택적

연결고리되는 컬럼의 index를 사용하지 않음

독립적

각 테이블은 다른 테이블에서 어떤 상수값도 제공받지 않고 주어진 상수값에 의해서만 범위를

전체범위처리

부분범위를 사용할 수 없음

Sort 안 함

SORT 를 하지 않으므로 SORT MERGE JOIN 보다는 좋은 성을을 내며, 작은 테이블과 큰 테이블의 JOIN 시에 유리

   

   

  1. Outer Join

   

   

   

Outer join 예)

   

예제1) 일반 조인의 경우

  • Outer Join을 했을 경우

   

SQL> SELECT DISTINCT(a.deptno), b.deptno
FROM emp a, dept b
WHERE a.deptno = b.deptno

  

   

   

   

화면 캡처: 2011-12-28 오후 5:34

   

   

   

화면 캡처: 2011-12-28 오후 5:35

   

   

SQL> SELECT DISTINCT(a.deptno), b.deptno
FROM emp a, dept b
WHERE a.deptno(+) = b.deptno

  

   

   

   

화면 캡처: 2011-12-28 오후 5:42

   

   

   

화면 캡처: 2011-12-28 오후 5:42

   

예제2)

   

   

   

화면 캡처: 2011-12-28 오후 5:48

   

첫번째 쿼리 결과를 잘 보면 Outer Join이 되지 않은 것을 알 수 있다.

  • Outer Join 조건이 걸려있는 테이블에는 다른 조건절이 들어와도 똑같이 Outer Join 연산자인 (+)를 해주어야 한다.

   

그 외 Outer Join..

   

  • 표준 Outer Join
  • Oracle9i 부터는 ANSI/ISO SQL 표준인 LEFT OUTER JOIN , RIGHT OUTER JOIN, FULL OUTER JOIN를 지원 한다.
  • LEFT OUTER JOIN과 RIGHT OUTER JOIN의 테이블 순서를 바꾸어 가면서 테스트를 하시면 쉽게 이해를 할 수 있다.

   

  1. LEFT OUTER JOIN
  • 오른쪽 테이블(아래 예제에서 emp 테이블)에 조인시킬 컬럼의 값이 없는 경우 사용한다.

 

SQL> SELECT DISTINCT(e.deptno), d.deptno
FROM dept d LEFT OUTER JOIN emp e ON d.deptno = e.deptno;

  1. RIGHT OUTER JOIN
  • 왼쪽 테이블(아래 예제에서 emp 테이블)에 조인시킬 컬럼의 값이 없는 경우 사용한다.


 

SQL> SELECT DISTINCT(e.deptno), d.deptno
FROM emp e RIGHT OUTER JOIN dept d ON e.deptno = d.deptno;

  1. FULL OUTER JOIN
  • 양쪽 테이블에 다 Outer Join을 거는것을 TWO-WAY OUTER JOIN 또는 FULL OUTER JOIN이라 한다.


 

SQL>SELECT DISTINCT(a.deptno), b.deptno
FROM emp a FULL OUTER JOIN dept b ON a.deptno = b.deptno;

   

   

  1. 그 외 Join들….

       

    1. CROSS JOIN

Cartesian Product 값을 얻을때 사용 한다.


 

-- 아래 SQL문장을 실행해 보자
SQL> SELECT ename
FROM emp CROSS JOIN dept

  1. INNER JOIN

    - 일반 조인시 ,(콤마)를 생략하고 INNER JOIN을 추가하고, WHERE절 대신 ON절을 사용하면 된다.

    - INNER는 생략 가능 하다.

    - 아래 두 조인의 결과 값은 같다.

       


 

-- INNER JOIN을 사용한 문장
SQL> SELECT e.empno, e.ename
FROM dept d INNER JOIN emp e ON d.deptno=e.deptno;


 

-- 일반적인 SQL 문장
SQL> SELECT e.empno, e.ename
FROM dept d , emp e WHERE d.deptno=e.deptno;

  1. NATURAL JOIN

    - Equi Join과 동일 하다고 보면 된다.

    - 두 테이블의 동일한 이름을 가지는 칼럼은 모두 조인이 된다.

    - 동일한 컬럼을 내부적으로 찾게 되므로 테이블 Alias를 주면 오류가 발생 한다.

    - 동일한 컬럼이 두개 이상일 경우 JOIN~USING 문장으로 조인되는 컬럼을 제어 할 수 있다.

    - 아래 두 조인의 결과 값은 같다.


 

-- NATURAL JOIN을 사용한 SQL 문장.
SQL> SELECT empno, ename, deptno FROM emp NATURAL JOIN dept


 

-- 일반적인 SQL 문장
SQL> SELECT e.empno, e.ename, d.deptno
FROM emp e, dept d WHERE e.deptno=d.deptno

  1. JOIN ~ USING

    - NATURAL JOIN의 단점은 동일한 이름을 가지는 칼럼은 모두 조인이 되는데, USING 문을 사용하면 컬럼을 선택해서 조인을 할 수가 있다.

    - USING절 안에 포함되는 컬럼에 Alias를 지정하면 오류가 발생 한다.


 

-- 일반적인 사용 방법
SQL> SELECT e.empno, e.ename, deptno
FROM emp e JOIN dept d USING(deptno)

  1. ON 구문

    - 조인 조건을 지정 할 수 있다.

    - 모든 논리 연산 및 서브쿼리를 지정할 수 있다.


 

-- 테스트를 위해 scott유저에서 아래 insert문장을 실행시킨다.
SQL> INSERT INTO bonus(ename, job, sal) VALUES('SMITH','CLERK',500);

-- ON절 사용 예제 (multi-table joins)
SQL> SELECT e.empno, e.ename, e.sal
FROM emp e JOIN dept d ON (e.deptno=d.deptno)
JOIN bonus b ON (b.ename = e.ename)
WHERE
e.sal IS NOT NULL

   

  • 부분범위 처리

   

  1. 부분범위 처리과정

   

   

  1. Union All

    - Union 이란 자신과 다른 집합의 합집합을 구할 경우에 사용하며 결과과 Unique 해야 함

    ☞ 결과가 Unique 하기 위해서는 전체를 Sort 한 후 중복을 제거하는 과정을 거치므로 전체 처리범위를 엑세스하게 된다.

   

  • Union All

    ☞ Oracle7에서 추가된 기능

    ☞ 중복을 확인하지 않고 부분범위로 처리가 가능

    ☞ Union 사용시에는 두 결과가 중복되지 않는다면 Union All 로 변경해도 결과가 같으몰 전체범위 처리를 부분범위 처리로 변경할 수 있음

   

  1. Exists

    - Sub Query 란 Main Query 내에 SQL Query 를 기술하는 것

    ① 어떤 조건을 마족하는 집합여부를 확인 하는 것은 Exists 문을 활용하여 처리

    ② Exists 는 주어진 조건을 만족하는 첫 번째 레코드를 만나면 트랜젝션을 멈추게 됨

    ③ 전체범이가 아닌 부분범위 처리를 할 수가 있음.

   

   

  • Join 의 최적경로

   

1. 가장 효율적인 Join 경로는 논리적으로 이미 존재함. 이것을 단지 Optimizer 가 찾아 줄 뿐, 없는 경로를 새롭게 생성해 주는 것이 아님

   

2. Index, Cluster 등의 Optimizing Factor 에 대한 지정 방법을 통해 어떤 것이 최적의 경로인지를 알고 있어야 하며 과연 Optimizer 가 정확하게 그 경로를 찾아주는지를 판단할 수 있어야 함

   

3. 파단기준으로 Optimizer 는 Ranking 이라는 것을 사용하게 돔.

   

4. 특이한 경우의 처리를 위해서 Hint 나 사용제한 기능(Suppessing) 을 이용하여 Optimizer 를 지산이 원하는 엑세스 경로로 유도할 수 있어야 함

   

   

<참고문헌>

Oracle Database 11g : Adminstration Workshop

Oracle Database 10g Documentation Library - councepts

원본 위치 <http://www.oracleclub.com>

원본 위치 <http://www.oracleclub.com/lecture/1035>

원본 위치 <http://blog.daum.net/dmz7881/8873046>

원본 위치 <http://blog.daum.net/_blog/hdn/ArticleContentsView.do?blogid=0LDC4&articleno=4653786&looping=0&longOpen=>

'1. IT Story > DB' 카테고리의 다른 글

Oracle EXPLAIN PLAN/DBMS_XPLAN PACKAGE  (0) 2012.02.29
Oracle SQL과 옵티마이져  (0) 2012.02.29
Oracle SQL Sub-query(기초)  (0) 2012.02.29
Oracle HINT(기초)  (0) 2012.02.29
Oracle SQL INDEX(기초)  (0) 2012.02.29
Oracle SQL Trace[기초]  (0) 2012.02.29
아카이브 로그 모드 Archive Log Mode  (0) 2012.02.29
Oracle TableSpace  (0) 2012.02.29
블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,


인덱스(Index)

   

  • 인덱스의 정의

       

    • 인덱스는 테이블이나 클러스트에서 쓰여지는 선택적인 객체로서, 오라클 데이터베이스 테이블내의 원하는 레코드를 빠르게 찾아갈 수 있도록

      만들어진 데이터 구조이다.

       

자동 인덱스 : 프라이머리 키 또는 UINQUE 제한 규칙에 의해 자동적으로 생성되는 인덱스.

수동 인덱스 : CREATE INDEX 명령을 실행해서 만드는 인덱스

   

   

원본 위치 <http://www.gurubee.net/pages/viewpage.action?pageId=983179>

   

  • 인덱스 사용 목적

       

    테이블의 검색 속도를 향상시키는 선택적 구조

       

       

    화면 캡처: 2011-12-26 오전 11:28

       

       

    • 인덱스의 장점

         

      성능 향상 효과

      - 일반적으로 테이블의 일부분만 활용하는 쿼리가 대부분이기 대문에 FTS 에 비해 물리적인 디스크 I/O가 적음

      - INDEX를 이용하여 별도의 정렬 없이 인덱스 순서대로 결과 추출 가능함

       

    • 인덱스의 단점

         

      성능 저하

      - 부정형의 질의문에는 사용되지 않음

      - 비트맵 인덱스에 비하면 저장 공간을 많이 차지함

      - 빈번한 DML 이 일어나면 트리의 밸런스가 부분적으로 저하되는 단점

       

       

  • 인덱스의 종류

       

    화면 캡처: 2011-12-26 오전 10:33

   

  • 인덱스를 생성하는 것이 좋은 컬럼

    ① WHERE절이나 join조건 안에서 자주 사용되는 컬럼

    ② null 값이 많이 포함되어 있는 컬럼

    ③ WHERE절이나 join조건에서 자주 사용되는 두 개 이상의 컬럼들

   

  • 다음과 같은 경우에는 인덱스 생성이 불필요 하다.

    ① 테이블이 작을 때

    ② 테이블이 자주 갱신될 때

       

       

  •  B-tree(binary search tree)

       

  • 오라클 인덱스는 B-tree(binary search tree)에 대한 원리를 기반으로 하고 있다. B-tree 인덱스는 컬럼안에 독특한 데이터가 많을 때 가장 좋은 효과를 낸다.

CREATE INDEX (index_name) ON (table)(컬럼) +@(tablespace~)

  

   

   

   

화면 캡처: 2011-12-26 오전 11:24

   

이 알고리즘 원리는 

① 주어진 값을 리스트의 중간점에 있는 값과 비교한다.만약 그 값이 더 크면 리스트의 아래쪽 반을 버린다. 만약 그 값이 더 작다면 위쪽 반을 버린다.

② 하나의 값이 발견될 때 까지 또는 리스트가 끝날 때까지 그와 같은 작업을 다른 반쪽에도 반복한다.

   

   

원본 위치 <http://www.gurubee.net/pages/viewpage.action?pageId=12517389>

   

   

   

원본 위치 <http://www.gurubee.net/pages/viewpage.action?pageId=12517389>

   

   

  • 비트맵 인덱스

   

   

   

화면 캡처: 2011-12-26 오전 10:23

   

   

   

화면 캡처: 2011-12-26 오전 10:23

   

   

원본 위치 <http://www.gurubee.net/pages/viewpage.action?pageId=3902465>

   

   

  • 비트맵 인덱스는 각 컬럼에 대해 적은 개수의 독특한 값이 있을 경우에 사용하는 것이 좋다.(ex 남,여의 값을 가지는 성별 컬럼)
  • 비트맵 인덱스는 B-tree 인덱스가 사용되지 않을 경우에서 성능을 향상 시킨다.
  • 테이블이 매우 크거나 수정/변경이 잘 일어나지 않는 경우에 사용할 수 있다.

       

    비트맵 인덱스는 lock 의한 DML 부하가 심한 것이 단점이다. 레코드 하나만 변경되더라도 해당 비트맵 범위에 속한

    모든 레코드에 lock이 걸린다. OLTP성 환경에 비트맵 인덱스를 쓸 수 없는 이유가 여기에 있다.

       

    원본 위치 <http://www.gurubee.net/pages/viewpage.action?pageId=3902465>

       

   

SQL> CREATE BITMAP INDEX bitmap_index ON bitmap_index_test(test_id);

  

   

  • Bitmap_index_test 테이블에 test_id 컬럼을 이용하여 bitmap_index를 생성.

   

   

   

화면 캡처: 2011-12-26 오전 10:58

   

  • UNIQUE 인덱스
  • UNIQUE 인덱스는 인덱스를 사용한 컬럼의 중복값들을 포함하지 않고 사용할 수 있는 장점이 있다.
  • 프라이머리키 와 UNIQUE 제약 조건시 생성되는 인덱스는 UNIQUE 인덱스이다.

       

SQL> CREATE UNIQUE INDEX unique_index ON unique_index_test(test_id);

  

   

  • unique_index_test 테이블에 test_id 컬럼을 이용하여 unique_index를 생성.

   

   

   

화면 캡처: 2011-12-26 오전 11:08

   

  • NON-UNIQUE 인덱스
  • NON-UNIQUE 인덱스는 인덱스를 사용한 컬럼에 중복 데이터 값을 가질 수 있다.

       

SQL> CREATE UNIQUE INDEX non_unique_index ON non_unique_index_test(test_id);

 

 

  • Non_unique_index_test 테이블에 test_id 컬럼을 이용하여 non_unique_index를 생성.

   

   

화면 캡처: 2011-12-26 오전 11:12

   

  • 결합 인덱스
  • 복수개의 컬럼에 생성할 수 있으며 복수키 인덱스가 가질 수 있는 최대 컬럼값은 16개이다

       

SQL> CREATE UNIQUE INDEX composte_index ON composite_index_test(test_id, name);

 

 

  • composite_index_test 테이블에 test_id, name 컬럼을 이용하여(결합) composite를 생성.

   

   

화면 캡처: 2011-12-26 오전 11:16

   

  • 인덱스의 삭제
    • 인덱스의 구조는 테이블과 독립적이므로 인덱스의 삭제는 테이블의 데이터에는 아무런 영향도 미치지 않는다.
    • 인덱스를 삭제하려면 인덱스의 소유자 이거나 DROP ANY INDEX권한을 가지고 있어야 한다.
    • 인덱스는 ALTER를 할 수 없다.

         

SQL> DROP INDEX bitmap_index;

  

 

   

화면 캡처: 2011-12-26 오전 11:40

   

   

  • 인덱스 데이터사전
    • 인덱스에 대한 정보는 USER_INDEXES 뷰 또는 USER_IND_COLUMNS뷰를 통해 검색할 수 있다.

         

SQL> SELECT index_name, index_type
FROM USER_INDEXES
WHERE table_name='COMPOSITE_INDEX_TEST';

 

   

INDEX_NAME

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

COMPOSITE_INDEX

INDEX_TYPE
-----------
NORMAL

 

   

   

화면 캡처: 2011-12-26 오전 11:36

   

   

  • 옵티마이저의 인덱스 선택 기준

       

    • = 조건으로 매칭되는 WHERE 절에 컬럼의 매칭률이 높은 것

            

    • 인덱스 컬럼의 매칭률이 같은 경우 단일컬럼 인덱스 보다 결합인덱스를 사용
    • 인덱스 컬럼의 매칭률과 인덱스의 종류(결합인덱스나 단일 컬럼인덱스)가 같을 경우 최근 생성된  인덱스를 사용

       

  • 인덱스 UNIQUE SCAN 과 RANGE SCAN

       

    • UNIQUE 인덱스의 구성 컬럼 모두에 대한 WHERE 조건절에서 'EQUAL(=) 상수' 를 받을 때 UNIQUE SCAN을 함
    • UNIQUE 인덱스의 구성 컬럼 무도와 'EQUAL(=) 상수' 를 만족하지 못하면 RANGE SCAN 함
    • NON UNIQUE 인덱스는 RANGE SCAN을 사용함

       

  • INDEX 와 CLUSTER 의 사용 비교

       

  • Clustered 여부에 따른 분류

       

       

 Clustered Index

 넓은 분포도를 가지고 있어 Index 활용이 어려운 경우 생성

 Non-Clustered Index

 일반적인 Index

   

  • Clustered란 ?

    1. 지정된 컬럼 값의 순서대로 로우를 저장시키는 방법

    2. 엑세스 기법이 아니라 엑세스 효율향상을 위한 물리적 저장기법

    3. INDEX 와 CLUSTER 의 사용 비교

   

   

Index 사용 시

일반적인 인덱스를 사용하는 경우 인덱스를 구성하는 컬럼들의 모든 값들이 인덱스에 존재한다.

인덱스를 Search한 후 rowid로 table를 acess하고 또다시 다음 인덱스 로우에 대하여 테이블 로우를 rowid 로 access한다.

Clustered 사용 시

인덱스를 구성한 컬럼의 한개의 값만 CLUSTER INDEX에 존재하며 CLUSTER INDEX 의 rowid로 table 을 access 한 후 계속적으로 테이블을

scan한는 방식

   

  • 사용시 유리한 경우

    ☞ 다량범위 데이터에대한 검색을 자주하는 경우

    ☞ 넓은 분포도를 가지고 있어 INDEX 활용이 어려운 경우

    ☞ 수정이 자주 발생하는 않는 컬럼

    ☞ 여러개의 테이블이 자주 JOIN 하는 경우

    ☞ ORDER BY, GROUP BY, UNION, DISTINCT 가 자주 발생하는 컬럼

       

  • 사용시 주의점

    ☞ INSERT, UPDATE, DELETE 처리시 OVERHEAD 발생

    ☞ CLUSTER KEY 의 최대 컬럼수는 16

    ☞ CLUSTER KEY 의 수정은 자주 발생하는 않아야 함

    ☞ INDEX 사용이 가능한 범위의 데이터는 효과가 크지 않음

    ☞ CLUSTER를 생성하면 기존의 INDEX는 재구성

    ☞ CLUSTER KEY 별 ROW 수의 편차가 심하지 않을 것

    ☞ CLUSTER 된 테이블 JOIN 시 ROW 수의 연순으로 FROM 절에 기술 할 것

    ☞ INDEX 와 CLUSTER 의 ACCESS 역할 분담 명확화

   

  • 인덱스 사용시 고려사항

       

  • 인덱스의 적용대상

    1. 중.대 구모 테이블(6블럭 이상)

    2. 대상 데이터의 10% 이내의 데이터 요구인 경우

    3. 스캔의 범위를 줄이고자 할때

    4. 정렬을 필요로 하는 경우

    5. 테이블에 접근하지 앟고 인덱스만으로 데이터 요구를 해결하고자 하는 경우

       

  • 인덱스 적용시 고려사항

    1. 인덱스를 위한 추가적 기억공간 필요

    2. 인덱스와 테이블 I/O 수의 합계가 전체 테이블을 스캔하는 I/O 수 보다 적은 경우만 성능향상에 기여(손익분기점:10~15%)

    3. 여러 컬럼을 결합하여 인덱스를 구성하는 경우 컬럼의 순서가 중요

    4. 입력, 삭제, 혹은 인덱스 컬럼의 값을 수정하는 경우 인덱스 데이터도 변경되어야 하므로 그에 따른 오버헤드 고려필요

       - 테이블당 인덱스 수는 4개가 적당

    5. 새로 추가된 인덱스는 기존 SQL문의 실행계획에 영향을 미칠 수 있음

       

  • 인덱스 대상 테이블 선정 기준

    1. 크기가 5~6 블럭 이상되는 테이블 : 이하는 FULL SCAN 해동 무방

    2. 무작위접근(Random Access) 이 빈번한 테이블 : 단순보관용 또는 전체조회용일 경우 인덱스 생성X

    3. 특정범위/순서의 데이터 조회가 필요한 테이블

    4. Join 의 연결고리가 되는 컬럼의 경우

    5. 참조모결성을 지정한 경우 연결고리가 되는 컬럼의 테이블

       

  • 인덱스 대상 컬럼 선정 기준

    1. 인덱스를 생성하고자하는 컬럼의 분포도는 5%를 넘지 않아야함.

       분포도 = 1/컬럼값의종류*100 = 데이터별 평균로우 수 / 테이블의 총 로우수 * 100

    2. 인덱스 머지(Index Merge) : 일반적으로 가장 좋은 하나의 인덱스만 사용하는 것이 여러개 인덱스를 사용하는 것보다 유리

    3. 결합 인덱스(Composite Index) : 사용빈도 => 동등조건(=)비교여부 => 분포도 => 자주 사용되는 정렬 순서

       

  • Index Fast Full Scan vs Index Full Scan

       

       

  • Index Full Scan

    개념 : Full scan은 Full scan으로 인한 부하가 발생하는 Access Operation이지만 Index 순서로 데이터를 추출 하므로 정렬을 하지 않아도 되는 장점을 가지고 있다.

       

    고려 사항

    Table의 대부분을 Access하여 정렬하는 경우라면 Index Full Scan을 통해 정렬된 결과를 추출할 수 있으므로

    성능을 보장해 줄 수 있다. 하지만 Table의 일부분만을Scan할 경우에 Index Full Scan을 수행하게 되면 모든

    Row를 가져와서 버리는 결과를 초래, 디스크 I/O 발생 및 Check하여 버리는 부하가 증가 하게 된다

       

  • Index Fast Full Scan

    개념 : - Index Full Scan은 Single Block I/O를 지원하게 되지만 Index Fast Full Scan은 Multi Block I/O를 한다

    Sort의 기능은 지원하지 않는다.

    - Multi Block의 수는 db_file_multiblock_read_count 파라미터에 의해 정의된다.

1) 인덱스 트리 구조를 무시하고 인덱스 세그먼트 전체를 multiblock read 방식으로 스캔

2) 인덱스가 파티션 있지 않더라도 병렬 쿼리 가능

3) 인덱스 리프 노드가 갖는 연결 리스트 구조를 이용하지 않기 때문에 얻어진 결과집합이 인덱스 순서대로 정렬되지 않음

   

   

   

<참고문헌>

대용량 데이터베이스 솔루션

Oracle Database 11g : Adminstration Workshop

Oracle Database 10g Documentation Library - councepts

원본 위치 <http://www.oracleclub.com>

원본 위치 <http://tistory.izyou.net/2460909>

원본 위치 <http://www.oracleclub.com/lecture/1035>

원본 위치 <http://blog.daum.net/_blog/hdn/ArticleContentsView.do?blogid=0LDC4&articleno=4653786&looping=0&longOpen=>

원본 위치 <http://www.gurubee.net/display/DBSTUDY/INDEX+FAST+FULL+SCAN>

   

   

'1. IT Story > DB' 카테고리의 다른 글

Oracle SQL과 옵티마이져  (0) 2012.02.29
Oracle SQL Sub-query(기초)  (0) 2012.02.29
Oracle HINT(기초)  (0) 2012.02.29
Oracle SQL Driving Table & JOIN(기초)  (0) 2012.02.29
Oracle SQL Trace[기초]  (0) 2012.02.29
아카이브 로그 모드 Archive Log Mode  (0) 2012.02.29
Oracle TableSpace  (0) 2012.02.29
Oracle Undo seg  (0) 2012.02.29
블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,