상세 컨텐츠

본문 제목

2024년 2월 2일 2교시 SQL문의 처리단계 1. parse - 3. 하드 파싱

오라클 퍼포먼스 튜닝

by 병아리 엔지니어 2024. 2. 2. 12:00

본문

 

서버 프로세스는 서버 쪽에 만들어진다. (절대로 클라이언트 쪽에 만들어지지 않는다)

서버 프로세스가 서버 쪽에 있다는 말을 그림으로 설명하면 위와 같다.


 

★ select 문의 처리 단계 (DML 은 3 단계, select 문은 4단계)

 

1. parse

parse 3) 하드 파싱 hard parsing

          - 동일한 SQL 문이 있는지 LC 에서 찾아봤는데 없는 경우 발생

            (하드 파싱 단계는 옵셔널한 단계: 동일한 SQL 문이 LC 안에 있어서

             소프트 파싱이 발생하는 경우 이 단계를 거치지 않고 바로 execute 단계로 간다)

          - 실행 계획을 새롭게 생성해야 한다.

          - LC 안에 실행 계획을 생성할 메모리 공간을 확보해야 하고

            그러기 위해서는 래치 latch 를 잡아야 한다.

          -  만약 래치를 잡지 못했을 경우에는 래치 쉐어드 풀 웨이트 이벤트 latch: shared pool wait event 발생

             (다른 유저에게 하드 파싱이 발생하는 중이라는 뜻,

              하드 파싱이 발생하면 무조건 메모리를 확보해야 하는데

              그 메모리를 확보하기 위한 웨이트 이벤트가 바로 저 래치 쉐어드 풀 웨이트 이벤트)

          - 라이브러리 캐시 안에는 Hash Bucket 이라는 공간이 있는데

            그 안에는 hash value 1, 2, 3, ... 값이 들어 있다.

          - 만약 찾고자 하는 데이터를 조회하는 SQL 문을 던졌을 경우 > 해시밸류 값을 할당받고

            그 해시밸류값을 가지고 SQL 문을 찾으러 가는데

            1번 해시밸류값을 할당받았을 경우 > 그 값을 가지고 hash Bucket 으로 가서

            > 기차처럼 연결된 LCO 를 뒤적거리며 SQL 문을 찾아본다.

            그런데 첫 번째 LCO 에 내가 찾는 SQL 문이 없으면 다음 LCO 로 넘어가고

            > 또 없으면 또 다음 LCO 로 넘어가고 > ...

            1번 해시밸류값의 마지막 LCO 까지 찾아봤는데 없으면

             > 맨 끝에 새로운 LCO 를 만들어서 문장을 저장한다.

           - 만약 프리공간이 확보되지 않을 경우 ORA-04031 오류가 발생할 수 있다.

           - LCO 의 크기는 매우 다양해서 (DBC 에서처럼 정해진 블록 크기가 있는 것이 아니다)

             서로 다른 메모리 공간이 ShP 안에 여러 개 만들어지게 된다.

             그래서 하드 파싱이 많이 발생하면 프리 공간의 청크들에 너무 단편화가 많아진다.

             (프리 공간이 있긴 한데 내가 필요한 만큼의 공간은 없고 너무 작게 조각나 있는 것,

              예를 들어 프리 조각이 7K, 10K, 1K, 100byte 이렇게 있는데

              내가 8K 만큼의 프리 공간만 필요로 한다면 > 10K 짜리를 쓰고 2K 는 프리로 놔두면 되지만

              - 8K 짜리 청크가 만들어지는 것

              내가 12K 만큼의 프리 공간을 필요로 할 경우

              12K 만큼의 프리 공간을 확보하기 위해서 래치를 잡고 프리 검색을 하는데

              그만큼의 프리 공간은 없다 > 이럴 때도 ORA-04031 오류가 발생한다.)

             하드 파싱 많이 발생 → 단편화 발생

            - 해결방법: ShP을 flush 하는 것

              디스크에 대한 조각 모음은 해주지만 메모리에 대한 조각 모음은 해주지 않아서 우리가 직접 해야 한다.

              그 메모리 조각 모음은 ShP 를 flush 해서 할 수 있는데

              flush 하면 원래 있던 메모리 다 지워지고 > 처음부터 다시 시작

              (이건 조각조각 이어붙이는 게 아니라 그냥 통째로 다 지워버리는 거잖아... 이걸  coalesce라고 해야 할지... 흠)

            - 만약 프리를 확보한 경우: LCO 생성

               LCO: Library Cache Object

               그런데 LCO 를 생성하려면 또 래치를 잡아야 한다.

               이 때 래치: 라이브러리 캐시 락 library cache lock (exclusive) 이 발생

               (똑같은 LCO 를 A는 생성하고 B는 보려고 할 때, 보려고 하는 유저 B 쪽에 뜨는 웨이트 이벤트)

             - LCO 가 생성되면 library cache lock 은 null 모드로 바뀐다. (exclusive > lock)

               그래서 다른 유저가 LCO 를 볼 수 있다.

             - LCO 가 생성되면 이제 그 안에 실행 계획을 만들어야 하는데

               그 때도 누가 와서 보면 안된다. (작업이 끝날 때까지 LCO 가 바뀌면 안되기 때문)

               그래서 해당 LCO에 일종의 시침핀 같은 것을 찍어놓는데 그게 바로 라이브러리 캐시 핀 library cache pin

             - latch: library cache pin 을 exclusive 모드로 찍어놓고 실행계획을 생성한다.

               이 웨이트 이벤트 역시 해당 LCO 를 읽으려고 하는 유저 B 쪽에 발생

               실행계획을 만드는 주체인 A 유저 쪽에는 발생하지 않는다.

             - LCO 도 LCO 안의 SQL 문이 있으면: share 모드 / 그러나 LCO나 그 안의 실행계획이 없으면 : exclusive 모드

               이런 경우에 해당 LCO 를 보려고 하는 유저 쪽에 웨이트 이벤트가 발생하는 것

             - 실행 계획 생성이 끝나면: execute 단계로 넘어간다.

 

2. bind

3. execute

4. fetch

관련글 더보기