Select 문장의 실행 원리


1. Parse 단계


 - 사용자가 SQL문장을 실행하면 User Process가 Server Process를 찾아와서 해당 SQL 문장을 전달.

 - 전달 받은 서버 프로세스는 해당 SQL 문을 처리하는데 가장 먼저 SQL Parser를 통해서 각 SQL 문장에 쓰인 키워트나 커럼명 등을 분석해서 Parse Tree를 생성.

 - Parse Tree를 만드는 과정에서 문법검사 (Syntax Check)를 하게 되고 이상이 없으면 구문검사 (Semantic Check)를 해서 의미상 오류 검사를 진행.

 - 오라클 키워드 (SELECT, FROM, WHERE 등) 의 스펠링이 틀릴 경우 Parse Tree 생성단계에서 에러 발생.

 - 키워드의 스펠링이 맞으나 테이블이 없다면 Semantic Check 단계에서 에러 발생.

 - 해당 문법이 맞는지 틀린지 여부나 해당 테이블이 있는지 없는지 여부를 알기 위해 데이터 딕셔너리를 사용.

 - 자주 사용하는 데이터 딕셔너리를 캐싱해 두어서 성능을 높이는 역할을 하는곳이 Shared Pool 안에 있는 Data Dictionary Cache(=Row Cache)라고 한다.


 - 위 과정을 거쳐 오류가 없다면 SQL문장을 ASCII 값으로 변경 한후 HASH 함수를 통해 특정 HASH 값 으로 변경.

 - 추출 된 Hash Value를 Library Cache에 있는 Hash Value들과 비교해서 동일한 값이 있는지 확인. 커서공유 또는 Soft Parse라고 부름.

 


  커서란?


 - 메모리에 어떤 데이터를 저장하기 위해 만든 임시 저장 공간. 실제 데이터가 들어가 있다.

 - 일반적으로 3가로 분류. 공유 커서, 세션 커서, 어플리케이션 커서.

 - 공유 커서의 역할은 이미 한번 수행한 SQL 문장의 실행 계획과 관련된 정보를 가지고 있다가 재활용하여 Hard Parse의 부담을 줄여 SQL문장의 수행속도를 높이는 것.

 - 동일한 SQL 문장이라고 하더라도 항상 커서 공유를 하는 것이 아님. 사용자가 다르거나 옵티마이져 모드가 다르면 커서 공유를 할 수 없다.

 - 공유 커서는 크게 부모 커서(Parent Cursor)와 자식 커서(Child Cursor)로 나뉘어 짐. SQL문장 자체에 대한 값은 부모 커서에, 사용자 정보나 옵티마이저 모드 정보는 자식 커서에 존재하게 된다.

 - 사용자가 많아 커서가 늘어나면 일일히 커서를 방문해 해당 내용이 있는지 없는지 찾지 못하기 때문에 Hash List를 만들어 관리 한다.

 - 메모리는 순서대로가 아닌 빈공간에 랜덤으로 들어가는데(heap 구조), 이 것을 관리 하는 Hash List를 통해 빠르게 커서의 위치를 찾는것.

 - Library Cache 안에서 원하는 SQL 문과 실행계획이 들어 있는 커서를 찾기 위해서는 반드시 Hash List를 읽어야 한다는 사실.



2. Bind 단계


 - 같은 테이블의 같은 컬럼을 조회하는 SQL이니까 파싱을 1,000번 하고 실행계획을 1,000개 만드는 것보다 1번만 파싱해서 실행 계획을 1개만 생성 한 후 변수값만 바꾸어서 1,000번 실행 하는 것이 부담도 적고 속도도 빠르다.  이러한 과정을 Bind 라고 한다.

 - 바인드 변수 사용시 Soft Parse를 많이 하게되지만 테이블에 입력 되어 있는 데이터들이 한쪽으로 편중되어 (Skewed) 있게 되면 insdex가 정상적으로 작동 하지 않음.

 - Skewed 의 뜻은 테이블에 있는 데이터 들이 균일한 비율이 아니라 특정 데이터가 집중적으로 많이 들어가 있다는 뜻. 이럴경우 특수 통계정보인 Histogram을 생성해 주어야 하나, 이 경우 Bind 기능을 사용 할 수 없다.

 - Bind 기능 덕분에 Hard Parse의 부담을 줄일수 있기 때문에 Bind를 사용하는 것을 추천.



3. Execute 단계


 - Parse와 Bind 단계를 거치고 나면 서버 프로세스는 해당 데이터를 가져오기 위해 해당 데이터가 저장 되어 있는 블록을 찾게 된다.

 - 모든 데이터는 SGA 구성요소인 Database Buffer Cache에 존재해야 한다. 조회와 변경 작업 모두 DB Buffer Cache 내에서 이루어 지기 때문.

 - Database Buffer Cache안에 필요로 하는 데이터가 없는 경우 Datafile에서 해당 내용을 찾아 DB Buffer Cache (메모리)로 복사 해온다.

 - Execute(실행)이란 단계는 하드 디스크의 데이터 파일에서 데이터가 들어 있는 블록을 찾아 메모리(Database Buffer Cache)로 복사해 오는 과정을 말한다.


 

 Block 단위의 I/O


 - 오라클은 데이터 파일에서 Database Buffer Cache로 데이터를 복사해 오거나, 반대로 메모리에서 디스크로 저장 할 때 가장 최소 단위인 Block 단위로 움직인다.

 - 이 Block은 초기화 파라메터 파일에서 DB_BLOCK_SIZE로 크기가 결정되며, DB가 생성 되때 적용되어 그 이후에는 변경 할 수 없다.

 - Oracle 9i에서는 기본값이 4k이며 10g 버전에서는 8k로 상향되었다.

 - Block의 크기가 크면 I/O를 줄일수 있는 장점이 있으나 공간 낭비가 많이 발생 할수 있으며, 또 너무 작으면 I/O 지나치게 많아 질 수 있다.



4. Fetch 단계


 - Execute 단계가 실행 되고 나면 데이터가 Database Buffer Cache에 올라오게 되는데, 원하는 데이터만 있는 것이 아니라 다른 사용자의 데이터나 기존에 사용했던 데이터도 상주하고 있다. 이 중에서 사용자가 원하는 데이터만 골라내는 과정이 Fetch 이다.

 - 사용자가 Sort(정렬)등의 추가 작업을 요청 했을시 Fetch과정에서 Sort를 진행하여 데이터를 보내주는 것. 정렬이 발생하는 공간은 PGA.

'ORACLE > Oracle DBMS' 카테고리의 다른 글

Oracle Background Processes  (0) 2014.04.17
Update 문장의 실행 원리  (0) 2014.04.15
Select 문장의 실행 원리  (0) 2014.04.15
SQL 문장의 실행원리  (0) 2014.04.15
PGA  (0) 2014.04.09
SGA  (0) 2014.04.09