본문 바로가기
스터디/오라클 성능고도화 원리와 해법1

04.라이브러리 캐시 최적화 원리 - 03.라이브러리 캐시 구조

by 취미툰 2020. 1. 10.
반응형

라이브러리 캐시는 Shared Pool 내에 위치하며, SQL 공유 커서 및 데이터베이스 오브젝트(테이블,인덱스)에 대한 정보를 관리합니다. 그리고 여기에 저장되는 정보의 단위를 라이브러리 캐시 오브젝트(LCO)라고 부릅니다.

 

SQL 커서 뿐만 아니라 컴파일을 거친 프로시저, 함수, 패키지, 트리거 등 PL/SQL프로그램을 담는 PL/SQL Area도 라이브러리 캐시에 저장합니다. (실행가능 LCO)

뿐만 아니라 거기서 참조하는 테이블,인덱스, 클러스터 같은 데이터베이스 오브젝트 정보들도 동등하게 하나의 오브젝트로써 관리됩니다.(오브젝트 LCO)

스키마 오브젝트 정보는 데이터 딕셔너리 캐시에도 캐싱돼 있는데 라이브러리 캐시에 중복 저장하는 이유가 무엇일까요.

라이브러리 캐시에 스키마 오브젝트 정보를 캐싱하는 것은 LCO간 의존성을 관리하려는 데 목적이 있습니다. LCO 각각에는 자신을 참조하는 다른 실행가능 LCO(커서,함수,프로시저,패키지 등)목록을 갖습니다.

 

SQL>   select namespace,gets,pins,reloads,invalidations
  2* from v$librarycache

NAMESPACE
--------------------------------------------------
      GETS       PINS    RELOADS INVALIDATIONS
---------- ---------- ---------- -------------
SQL AREA
      4986      24106        171           179

TABLE/PROCEDURE
      6550       8812        124             0

BODY
       155        293          0             0


NAMESPACE
--------------------------------------------------
      GETS       PINS    RELOADS INVALIDATIONS
---------- ---------- ---------- -------------
TRIGGER
        28         28          0             0

INDEX
       159         93          0             0

CLUSTER
       494        566          0             0


NAMESPACE
--------------------------------------------------
      GETS       PINS    RELOADS INVALIDATIONS
---------- ---------- ---------- -------------
DIRECTORY
        20         20          0             0

QUEUE
         6          8          0             0

RULESET
         1          3          0             0


NAMESPACE
--------------------------------------------------
      GETS       PINS    RELOADS INVALIDATIONS
---------- ---------- ---------- -------------
SUBSCRIPTION
         2          2          0             0

EDITION
        39         75          0             0

DBLINK
         4          0          0             0


NAMESPACE
--------------------------------------------------
      GETS       PINS    RELOADS INVALIDATIONS
---------- ---------- ---------- -------------
OBJECT ID
         6          0          0             0

SCHEMA
      4288          0          0             0

DBINSTANCE
         2          0          0             0


NAMESPACE
--------------------------------------------------
      GETS       PINS    RELOADS INVALIDATIONS
---------- ---------- ---------- -------------
SQL AREA STATS
      1195       1195          0             0

SQL AREA BUILD
      1207          0          0             0

PDB
         7          0          0             0


NAMESPACE
--------------------------------------------------
      GETS       PINS    RELOADS INVALIDATIONS
---------- ---------- ---------- -------------
AUDIT POLICY
        26         26          0             0

PDBOPER
         3          0          0             0

FED APP
        16         16          0             0

 

21 rows selected.

 

위는 라이브러리 캐시에 어떤 유형의 오브젝트들이 적재되는지를 보여줍니다.

라이브러리 캐시에 캐싱되는 정보를 또 다른 측면에서 다음 두 가지로 나누어 볼 수 있습니다.

첫째는 생성 후 Drop하기 전까지 데이터베이스에 영구적으로 보관되는 오브젝트 정보입니다.

(테이블,인덱스,클러스터,뷰,트리거,패키지,사용자정의함수,프로시저 등) 이들 오브젝트는 생성될 때부터 이름을 갖는 것이 특집입니다.

둘때는 실행시점에 생성돼서 인스턴스가 떠있는 동안에만 존재하는 일시적인 오브젝트 정보입니다.(커서와 Anonymous PL/SQL) 이들은 이름을 따로 지정하지 않으며 문장을 구성하는 전체 문자열 그대로가 이름 역할을 합니다.

 

라이브러리 캐시는 데이터 딕셔너리 캐시와 함께 Shared Pool에 할당된 메모리 공간을 사용합니다. Shared Pool은 LRU 알고리금에 의해 관리되며 재사용 빈도가 낮은 SQL을 밀어냄으로써 새로운 SQL을 캐싱할 수 있도록 공간을 확보합니다.

 

Shared Pool에서 특정 오브젝트 정보 또는 SQL 커서를 위한 Free Chunk를 할당 받으려할 때 필요한 래치가 Shared pool래치입니다. 예전에는 하나의 Shared pool래치로 전체를 관리하였으나, 9i이후 여러개의 sub pool로 나누어 관리할 수 있게 되면서 7까지 사용할 수 있게 되었습니다.(19c 기준)

 

SQL> select child#,gets,misses,sleeps,immediate_gets,immediate_misses
  2  from v$latch_children
  3  where name = 'shared pool'
  4  order by child#;

    CHILD#       GETS     MISSES     SLEEPS IMMEDIATE_GETS IMMEDIATE_MISSES
---------- ---------- ---------- ----------
         1     138894         21         22              0                0
         2          6          0          0              0                0
         3          6          0          0              0                0
         4          6          0          0              0                0
         5          6          0          0              0                0
         6          6          0          0              0                0
         7          6          0          0              0                0

7 rows selected.

 

라이브러리 캐시도 DB 버퍼 캐시처럼 해시구조로 관리됩니다. 즉 해시 버킷에 LCO핸들(LCO를 식별하고 힙을 포인팅하는 데 사용)이 체인으로 연결돼 있고, 핸들을 통해 LCO힙을 찾아가는 구조입니다. DB 버퍼 캐시와 마찬가지로 해시 함수를 통해 리턴된 해시값을 가지고 해시 버킷을 할당합니다.

 

그림을 보면 오브젝트 LCO인 EMP테이블 정보와 실행가능 LCO에 해당하는 SQL 커서가 라이브러리 캐시에 함께 적재돼 있습니다. 그림에서 보듯이 커서는 Parent 커서 밑에 Child 커서가 연결되는 구조를 갖습니다. SQL문장이 100% 동일한대도 커서를 공유하지 못하고 커서를 별도로 생성해야 할 때가 있는데, 오라클은 그럴 때 다중 Child 커서를 사용합니다.

라이브러리 캐시 체인을 탐색하고 변경하려면 library cache래치를 획득해야 합니다. 이에 대한 경합이 발생할 때 latch : library cache 대기 이벤트가 발생합니다. 

LCO를 보호하려고 오라클은 라이브러리 캐시 Lock과 라이브러리 캐시 Pin을 사용합니다.

LCO에 접근할 때는 먼저 핸들에 대한 Lock을 획득해야 합니다. 그러고 나서 LCO의 실제 내용이 담긴 heap에서 정보를 읽거나 변경할 때는 pin을 걸어두어야 합니다.그럼으로써 실행하는 동안 다른 프로세스에 의해 정보가 변경되거나 캐시에서 밀려나는 것을 방지합니다.

shared pool 래치와 library cache 래치 경합은 소프트/하드 파싱을 동시에 심하게 일으킬 때 발생하고, library cache lock과 library cache pin 대기 이벤트는 주로 SQL 수행 도중 DDL을 날릴 때 발생합니다. 트랜잭션이 활발한 주간에 DDL문을 날려 데이터베이스 오브젝트 정의를 변경하려면 라이브러리 캐시에 심한 부하를 유발하므로 주의해야 합니다.

 

라이브러리 캐시 최적화를 위한 데이터베이스 관리자 측면에서의 튜닝기법

커서를 공유할 수 있는 형태로 SQL을 작성합니다. 특히 바인드 변수를 사용해 같은 형태의 SQL에 대한 반복적인 하드파싱이 일어나지 않도록 해야 합니다.

세션 커서 캐싱기능을 이용 해 라이브러리 캐시에서 SQL을 찾는 비용을 줄입니다.

애플리케이션 커서 캐싱을 이용해 Parse Call발생량을 줄입니다.

 

다음에 자세히 원리와 활용기법에 대해 알아보겠습니다.

반응형

댓글