현재 선택한 SQL 과정

SQLP 이론 학습

이론 목록으로 돌아가기

Cursor 재사용 계층: Library Cache·Session Cursor Cache·JDBC Statement Cache

Shared Pool 재사용을 넘어 Session Cursor Cache와 Prepared Statement 재사용으로 Parse Call 자체를 줄입니다.

예상 읽기 23

핵심 요약

같은 SQL을 반복 실행할 때의 재사용은 하나의 Cache로 끝나지 않습니다. 애플리케이션/JDBC, Session, Library Cache는 서로 다른 위치에서 서로 다른 비용을 줄입니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
애플리케이션·Oracle JDBC/UCP Statement Cache
→ Statement Object·Database Cursor 재생성, 반복 Prepare와 통신 비용을 줄임

Session Cursor Cache
→ 같은 Session이 닫은 Session Cursor의 Shared Child Cursor 참조를 보관
→ 후속 Parse Call의 실제 Reparse 작업을 피하거나 줄임

Library Cache
→ Shared Pool의 Parsed·Executable SQL과 PL/SQL을 여러 실행·Session이 공유
→ Hard Parse와 실행구조 재생성 비용을 줄임

따라서 다음 두 문장은 같은 뜻이 아닙니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Hard Parse가 적다
≠ Parse Call이 적다

Session Cursor Cache Hit가 발생했다
≠ 애플리케이션이 Parse Call을 보내지 않았다

Session Cursor Cache에서 Cursor를 재사용해도 Parse Call 통계에는 기록될 수 있지만 실제 Reparse는 피할 수 있습니다. Database에 전달되는 Prepare·Parse 요청 자체를 줄이려면 애플리케이션이 Prepared Statement를 계속 열어 재실행하거나, Oracle JDBC/UCP의 Statement Cache가 같은 Physical Connection에서 Statement를 재사용해야 합니다.


학습 목표

  • Parse Call, Reparse, Soft Parse, Hard Parse의 관계를 구분한다.
  • Library Cache, Session Cursor Cache, JDBC Statement Cache의 저장 위치와 재사용 범위를 설명한다.
  • Session Cursor Cache가 활성화되는 반복 기준과 통계 해석 방법을 설명한다.
  • SESSION_CACHED_CURSORSOPEN_CURSORS가 독립적인 Parameter인 이유를 설명한다.
  • Connection Pool의 Physical Connection별 Statement Cache와 Open Cursor 자원 총량을 계산한다.
  • V$SESSTAT, V$SQLSTATS, V$OPEN_CURSOR, V$SQL_SHARED_CURSOR를 연결해 Parse 비용을 진단한다.
  • Cache 크기 확대보다 SQL Text·Bind·Statement 생명주기 개선을 우선한다.

1. 먼저 재사용 계층과 Cursor 종류를 구분한다

SQL 실행에는 다음 요소가 서로 연결됩니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Application Statement Object
→ Database Session Cursor
→ Shared Child Cursor
→ Library Cache의 실행 가능한 구조
계층대표 저장 위치재사용 단위주로 줄이는 비용
애플리케이션 Prepared Statement애플리케이션 Process같은 Statement Object반복 Prepare·Parse 요청, Client 객체 생성
Oracle JDBC/UCP Statement CachePhysical Connection별 Client Cache동일 SQL·Statement Type·Result Set TypeCursor·Statement 재생성과 통신·Parse 요청
Session Cursor CacheDatabase Session Memory같은 Session이 반복한 닫힌 Session Cursor실제 Reparse와 Library Cache 탐색 경로
Library CacheShared Pool공유 가능한 Parent·Child CursorHard Parse·Optimization·실행구조 생성

여기서 Session Cursor는 특정 Session이 Shared Child Cursor를 사용하는 인스턴스입니다. Library Cache의 Shared Child Cursor와 Session Cursor는 같은 객체가 아닙니다.


2. Parse Call·Reparse·Soft Parse·Hard Parse

2.1 Parse Call

Parse Call은 애플리케이션이나 Database 내부 코드가 SQL을 사용할 수 있도록 준비를 요청한 횟수입니다. parse count (total)에는 Hard·Soft·Describe Parse Call이 포함됩니다.

2.2 Soft Parse

Library Cache에 공유 가능한 Parsed Representation이 있어 재사용하는 경우입니다. Optimizer가 새 실행계획을 만드는 Hard Parse는 피하지만 다음 비용이 완전히 0이 되는 것은 아닙니다.

  • SQL Text와 Shared Cursor 탐색
  • 참조 객체·권한·Session 환경 확인
  • Shared Child Cursor의 공유 가능성 검사
  • Library Cache 관련 동기화와 CPU

2.3 Hard Parse

공유 가능한 실행구조가 없거나 기존 구조를 사용할 수 없어 새로운 실행 가능한 형태를 만드는 경우입니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
문법·의미 분석
→ 객체·권한 확인
→ Query Transformation
→ Cardinality·Cost 추정
→ 실행계획과 Row Source 생성
→ Library Cache 등록

Hard Parse는 Soft Parse보다 CPU·Memory·동기화 비용이 큽니다. 그러나 Hard Parse 비율이 낮더라도 실행마다 Soft Parse가 발생하면 전체 Parse CPU와 확장성 비용은 커질 수 있습니다.

2.4 Session Cursor Cache Hit의 통계적 의미

Session Cursor Cache에서 재사용해도 Oracle 공식 설명상 Parse Call로 등록됩니다. 반면 session cursor cache hits는 해당 SQL 또는 PL/SQL이 실제로 Reparse될 필요가 없었던 횟수입니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
대략적인 실제 Parse 작업 횟수
= parse count (total) - session cursor cache hits

이 계산은 Session Cursor Cache 효과를 해석하는 보조 지표입니다. 애플리케이션이 보내는 Parse Call 자체를 측정하려면 Application Trace와 parse count (total)의 구간 Delta를 함께 봅니다.


3. Library Cache: Shared SQL과 실행구조 재사용

Library Cache는 Shared Pool에서 최근 사용한 SQL·PL/SQL의 Parsed·Executable Form을 관리합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Parent Cursor
→ SQL Text와 SQL_ID를 중심으로 Statement를 식별

Child Cursor
→ 실행계획·Bind Metadata·Optimizer 환경·참조 객체 등
→ 실제 공유 가능 조건을 만족하는 실행 가능한 형태

3.1 공유 조건

일반적인 Exact Sharing에서는 다음 조건이 중요합니다.

  • SQL Text가 공백·대소문자·주석까지 문자 단위로 동일
  • 참조하는 Schema Object가 동일
  • Bind 이름·Data Type·길이가 호환
  • Optimizer Goal과 Session 환경이 호환
  • 기존 Cursor가 유효하고 필요한 실행구조가 Memory에 존재

다음 SQL은 업무 의미가 비슷해도 Text가 달라 별도 Parent Cursor가 될 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT customer_name FROM customer WHERE customer_id = 1001;
SELECT customer_name FROM CUSTOMER WHERE customer_id = 1002;

Bind를 사용해 Text를 안정화합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT customer_name
FROM   customer
WHERE  customer_id = :customer_id;

3.2 Child Cursor 증가

SQL_ID가 같아도 Bind Metadata, Optimizer 환경, Object 상태, 권한, Adaptive Cursor Sharing 등의 이유로 여러 Child Cursor가 존재할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT sql_id,
       plan_hash_value,
       executions,
       parse_calls,
       loads,
       invalidations,
       version_count,
       avg_hard_parse_time,
       SUBSTR(sql_text, 1, 100) AS sql_text
FROM   v$sqlstats
WHERE  sql_id = :sql_id;

VERSION_COUNT가 높다는 사실만으로 원인을 확정하지 않습니다. 동일 SQL의 공유 실패 사유는 V$SQL_SHARED_CURSOR의 Flag를 확인하고, Bind Metadata·Optimizer 환경·Invalidation 이력을 함께 분석합니다.

3.3 Load와 Invalidation

  • LOADS: SQL Object가 Library Cache에 Load 또는 Reload된 횟수
  • INVALIDATIONS: 의존 객체 변경 등으로 Child Cursor가 Invalid 처리된 횟수
  • V$LIBRARYCACHE.RELOADS: 이전에 Cache됐던 Object를 다시 Load해야 했던 활동

이 값들은 누적값이므로 Instance 시작 이후 총량만 보지 말고 장애 전후 Delta를 비교합니다.


4. Session Cursor Cache: 닫힌 Session Cursor의 참조 재사용

SESSION_CACHED_CURSORS는 각 Session이 Cache할 수 있는 닫힌 Session Cursor 수의 최대값입니다. Oracle AI Database 26ai의 기본값은 50입니다.

4.1 Cache 진입 조건과 동작

공식 동작은 다음과 같습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
같은 Session에서 동일 Statement Parse·사용
→ Cursor Close가 반복됨
→ 세 번 닫힌 뒤 반복 Statement로 판단
→ Session Cursor Cache에 Shared Child Cursor 참조 보관
→ 후속 Parse Call에서 Session 배열의 Pointer 탐색
→ Session·System 환경이 호환되면 재사용

Cache는 LRU 방식으로 공간을 확보하고, 장시간 유휴 Cursor는 내부 시간 기준으로 Aging될 수 있습니다.

중요한 점은 Session Cursor Cache가 Parse Call을 애플리케이션에서 제거하는 기능이 아니라는 것입니다. 재사용은 Parse 통계에 기록될 수 있지만 실제 Reparse 작업과 Shared Cursor 탐색 비용을 줄입니다.

4.2 SESSION_CACHED_CURSORSOPEN_CURSORS는 독립적이다

Parameter목적Cursor 상태
OPEN_CURSORS한 Session이 동시에 열 수 있는 Cursor Handle의 최대 수Open
SESSION_CACHED_CURSORS닫힌 Session Cursor를 Session Cache에 유지하는 최대 수Cached Closed

Session Cursor Cache의 Cursor는 Open 상태가 아니므로 SESSION_CACHED_CURSORSOPEN_CURSORS보다 크게 설정할 수도 있습니다. 둘의 기본값이 모두 50이더라도 역할은 다릅니다.

4.3 Session 통계

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT n.name,
       s.value
FROM   v$sesstat s
JOIN   v$statname n
  ON   n.statistic# = s.statistic#
WHERE  s.sid = :sid
AND    n.name IN (
         'parse count (total)',
         'parse count (hard)',
         'parse time cpu',
         'parse time elapsed',
         'session cursor cache hits',
         'session cursor cache count',
         'opened cursors current',
         'opened cursors cumulative'
       )
ORDER BY n.name;

다음 조건이 함께 성립할 때 증설을 검토합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
같은 Session이 동일 SQL을 반복 Parse
+ session cursor cache count가 설정 최대값에 가까움
+ session cursor cache hits / parse count (total)이 낮음
+ Application Statement 재사용만으로 해결되지 않음

단순히 Count가 최대값에 가깝다는 이유만으로 확대하지 않습니다. SQL 종류가 계속 바뀌는 Dynamic SQL이라면 Cache를 키워도 Hit가 개선되지 않을 수 있습니다.

4.4 V$SESSION_CURSOR_CACHE의 한계

V$SESSION_CURSOR_CACHE는 현재 Session의 MAXIMUM, COUNT, OPENS, HITS, HIT_RATIO를 보여 줍니다. 그러나 Oracle 공식 문서는 이 View가 SESSION_CACHED_CURSORS 효과를 측정하는 View가 아니라고 명시합니다.

따라서 다음을 함께 사용합니다.

  • 대상 Session의 V$SESSTAT Delta
  • 반복 SQL의 Application Trace
  • parse count (total)session cursor cache hits
  • Parameter 변경 전후 동일 부하의 CPU·응답시간

5. Oracle JDBC·UCP Statement Cache: Physical Connection별 재사용

Oracle JDBC Statement Cache는 반복 실행되는 Prepared·Callable Statement를 Client 측 Physical Connection에 보관합니다. Oracle은 Implicit Statement Cache 사용을 강하게 권장합니다.

5.1 Physical Connection별 Cache

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Connection Pool
├─ Physical Connection A → Statement Cache A
├─ Physical Connection B → Statement Cache B
└─ Physical Connection C → Statement Cache C

Logical Connection이 닫혀 Pool에 반환돼도 Underlying Physical Connection이 유지되면 그 Connection의 Cache를 이후 Logical Connection이 이용할 수 있습니다. 다음 요청이 다른 Physical Connection을 빌리면 다른 Cache가 적용됩니다.

5.2 Implicit Cache의 대상과 Matching

Implicit Statement Cache는 OraclePreparedStatementOracleCallableStatement에 적용됩니다. SQL String 없이 생성되는 일반 OracleStatement는 대상이 아닙니다.

Cache Hit를 위한 대표 조건은 다음과 같습니다.

  • SQL String이 대소문자를 포함해 동일
  • Prepared 또는 Callable Statement Type이 동일
  • 생성되는 Result Set의 Forward-Only·Scrollable Type이 동일

Implicit Cache가 활성화된 상태에서 Prepared/Callable Statement의 close()를 호출하면 Logical 사용은 종료되지만 Statement가 Cache로 반환될 수 있습니다. Cache에서 다시 꺼낼 때 State와 Data는 기본값으로 초기화되고 Metadata는 재사용됩니다.

5.3 UCP 설정과 기본 상태

UCP의 Statement Cache는 maxStatements가 설정되지 않았거나 0이면 비활성화됩니다. 크기는 Physical Connection당 Distinct Statement 수를 기준으로 산정하며, 무조건 큰 값이 정답은 아닙니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
예상 Client Statement Cache 최대량
= Physical Connection 수 × Connection당 Cache Size

Cached Statement는 Database Cursor 등 자원을 유지할 수 있으므로 Pool Connection 수와 Cache Size의 곱이 OPEN_CURSORS 한도와 Memory에 미치는 영향을 검증합니다.

5.4 구조 변경 주의

Statement를 생성·실행한 뒤 Table 구조를 변경하고 이전 Cached Statement를 재사용하면 오류가 발생할 수 있습니다. 배포 중 DDL과 장기 Connection Pool이 함께 있는 환경에서는 Cache Purge·Connection Refresh 정책을 준비합니다.


6. Prepared Statement 생명주기와 Bind

가장 직접적인 개선은 반복문 바깥에서 Prepared Statement를 한 번 준비하고 Bind 값만 변경해 실행하는 것입니다.

JAVA코드 영역 안에서 좌우로 이동할 수 있습니다.
String sql =
    "SELECT customer_name " +
    "FROM customer " +
    "WHERE customer_id = ?";

try (PreparedStatement ps = conn.prepareStatement(sql)) {
    for (long id : customerIds) {
        ps.setLong(1, id);

        try (ResultSet rs = ps.executeQuery()) {
            if (rs.next()) {
                // 결과 처리
            }
        }
    }
}

다음 구조는 동일 SQL을 반복 Prepare하고 Close하므로 Application Statement 재사용이 없습니다.

JAVA코드 영역 안에서 좌우로 이동할 수 있습니다.
for (long id : customerIds) {
    try (PreparedStatement ps = conn.prepareStatement(sql)) {
        ps.setLong(1, id);
        ps.executeQuery();
    }
}

JDBC Implicit Statement Cache가 활성화돼 있다면 두 번째 구조의 비용 일부를 줄일 수 있지만, 첫 번째 구조처럼 하나의 Statement Object를 직접 재실행하는 방식이 생명주기와 의도를 더 명확하게 통제할 수 있습니다.

Bind Variable은 Parent Cursor 폭증을 줄이는 핵심이지만 다음을 자동으로 해결하지는 않습니다.

  • Bind Data Type·길이 불일치
  • 데이터 편중과 Adaptive Cursor Sharing
  • Optional Predicate로 인한 Plan 부적합
  • Optimizer 환경 차이
  • Application의 반복 Prepare 구조

7. Open Cursor 자원을 정확히 계산한다

7.1 Server Session Cursor Cache와 JDBC Cache를 혼동하지 않는다

Session Cursor Cache는 닫힌 Session Cursor를 보관하며 OPEN_CURSORS와 독립적입니다. 반면 JDBC/UCP Statement Cache에 보관된 Statement는 Physical Connection과 Database Resource를 유지할 수 있어 Open Cursor 총량에 영향을 줄 수 있습니다.

7.2 V$OPEN_CURSOR

V$OPEN_CURSOR는 Session별로 Open·Parsed 또는 Cached Cursor를 나열하며 CURSOR_TYPE으로 상태를 구분할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT sid,
       cursor_type,
       COUNT(*) AS cursor_count
FROM   v$open_cursor
WHERE  sid = :sid
GROUP BY sid, cursor_type
ORDER BY cursor_count DESC;

V$OPEN_CURSOR의 전체 행 수를 곧바로 opened cursors current와 같다고 보지 않습니다. View에는 SESSION CURSOR CACHED, PL/SQL Cache 등 여러 Cursor Type이 포함될 수 있으므로 통계와 유형을 함께 봅니다.

7.3 누수와 정상 Cache 구분

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
opened cursors current가 요청 종료 후에도 지속 증가
+ 같은 SQL_ID·Cursor Type이 반복 누적
+ Application에서 ResultSet·Statement Close 누락
→ Cursor Leak 가능성

Statement Cache Size 변경 뒤 일정 수준에서 안정
+ Cache Hit 증가
+ 응답시간·Parse CPU 감소
→ 의도한 Cache 유지 가능성

8. SQL·Session·Application을 연결하는 진단 절차

8.1 SQL별 Parse 재사용

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT sql_id,
       plan_hash_value,
       executions,
       parse_calls,
       loads,
       invalidations,
       version_count,
       ROUND(parse_calls / NULLIF(executions, 0), 4) AS parses_per_exec,
       ROUND(avg_hard_parse_time / 1000, 3) AS avg_hard_parse_ms,
       SUBSTR(sql_text, 1, 100) AS sql_text
FROM   v$sqlstats
WHERE  executions > 0
ORDER BY parse_calls DESC
FETCH FIRST 30 ROWS ONLY;

V$SQLSTATS는 SQL_ID 단위로 집계되고 Cursor가 Shared Pool에서 Aging된 뒤에도 통계가 더 오래 남을 수 있습니다. 다음처럼 해석합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
PARSE_CALLS / EXECUTIONS가 높음
→ 실행마다 Parse 요청이 발생하는지 Application Trace 확인

LOADS·INVALIDATIONS 증가
→ Shared Pool Aging, DDL, Dependency 변경 확인

VERSION_COUNT 증가
→ V$SQL_SHARED_CURSOR에서 공유 실패 Flag 확인

Parse Call은 Execute 수보다 클 수도 있고 작을 수도 있습니다. Cursor가 한 번 Parse된 뒤 여러 번 Execute되거나, Parse만 하고 Execute하지 않는 경로, 여러 Session의 집계가 섞일 수 있기 때문입니다.

8.2 구간 Delta

누적 통계를 그대로 비교하지 말고 동일 부하 구간의 Delta를 사용합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
변경 전 10분
→ Session별 Total Parse·Hard Parse·Cache Hit·Parse CPU
→ SQL별 Parse Calls·Executions·Loads·Invalidations
→ Pool별 Physical Connection·Statement Cache Size
→ Open Cursor와 응답시간

변경 후 동일 10분
→ 같은 항목을 같은 요청량으로 비교

8.3 Application 식별 정보

Connection Pool 환경에서는 DBMS_APPLICATION_INFO 또는 Driver의 Module·Action·Client Identifier를 설정해 Session과 업무 요청을 연결합니다. 하나의 Session만 표본으로 보고 Pool 전체를 일반화하지 않습니다.


9. 개선 순서

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
1. 같은 업무 SQL의 Text·Bind가 안정적인가?
2. 반복문·요청마다 prepareStatement()를 다시 호출하는가?
3. 하나의 Prepared Statement를 Bind만 바꿔 재실행할 수 있는가?
4. Oracle JDBC/UCP Statement Cache가 Physical Connection별로 적절한가?
5. Physical Connection 수 × Cache Size가 OPEN_CURSORS·Memory 범위 안인가?
6. Session Cursor Cache Count·Hit·Total Parse Delta는 어떤가?
7. Library Cache의 Hard Parse·Loads·Invalidations·Version Count 원인은 무엇인가?
8. 변경 후 Parse CPU·응답시간·Open Cursor·Memory가 함께 개선됐는가?
개선 계층먼저 확인할 문제대표 증거주요 조치
SQL Text·BindLiteral·공백·Case·Bind Metadata 불안정SQL_ID 수, V$SQL_SHARED_CURSORSQL 표준화, Bind Type 통일
Application반복 Prepare·CloseApplication Trace, Parse DeltaStatement 생명주기 확대
JDBC/UCPPhysical Connection마다 Cache MissPool Metric, Cache SizeImplicit Cache·크기 조정
Session닫힌 Cursor의 반복 ReparseSession Cache Hit·CountSESSION_CACHED_CURSORS 조정
Library CacheHard Parse·Reload·InvalidationHard Parse, Loads, Invalidations공유 실패·DDL·Memory 원인 제거

Cache Parameter 확대는 마지막이 아니라 증거가 있는 계층에서만 수행하는 조치입니다.


혼동하기 쉬운 판단

단순 판단정확한 기준
Hard Parse가 적으면 Parse 문제가 없다반복 Soft Parse와 Parse Call 자체도 CPU·동기화 비용을 만든다
Session Cursor Cache Hit면 Parse Call이 없었다Parse Call로 기록될 수 있지만 실제 Reparse가 생략된다
Session Cursor Cache는 즉시 모든 SQL을 Cache한다같은 Cursor가 세 번 닫힌 뒤 반복 Statement로 판단해 Cache할 수 있다
SESSION_CACHED_CURSORS는 Open Cursor 수다닫힌 Session Cursor Cache의 최대 크기다
OPEN_CURSORS보다 Session Cache를 크게 설정할 수 없다두 Parameter는 독립적이며 Cached Session Cursor는 Open 상태가 아니다
Statement Cache는 Pool 전체에 하나다Physical Connection마다 별도 Cache가 있다
일반 Statement도 JDBC Implicit Cache 대상이다Prepared·Callable Statement가 대상이며 Plain Statement는 대상이 아니다
V$SESSION_CURSOR_CACHE만 보면 효과를 알 수 있다공식적으로 Parameter 효과 측정 View가 아니므로 V$SESSTAT·부하 Delta가 필요하다
V$OPEN_CURSOR 행 수가 현재 Open Cursor 수다Cached·PL/SQL 등 여러 Cursor Type을 포함할 수 있다
Cache는 클수록 좋다Connection 수·Open Cursor·Memory·Hit·응답시간을 함께 검증한다

핵심 판단 순서

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Parse Calls가 많은가?
→ Application이 Statement를 반복 Prepare하는가?
→ SQL Text와 Bind Metadata가 안정적인가?
→ 같은 Physical Connection에서 JDBC Cache가 Hit하는가?
→ Session Cursor Cache가 반복 SQL을 재사용하는가?
→ Library Cache의 Shared Child Cursor가 호환되는가?
→ Open Cursor·Memory 비용보다 CPU·응답시간 이득이 큰가?

스스로 확인하기

개념 확인 문제

문제를 누르면 바로 아래에서 정답과 해설을 확인할 수 있습니다.

01Parse Call과 Hard Parse가 같은 값이 아닌 이유는 무엇인가?
정답 및 해설

Parse Call은 SQL 사용 준비를 요청한 전체 횟수이고 Hard Parse는 그중 공유 가능한 실행구조가 없어 새 Parsed·Executable Form을 만드는 경우입니다. 기존 Shared Child Cursor를 사용하면 Soft Parse가 되며 Session Cursor Cache Hit도 Parse Call로 기록될 수 있습니다.

02Library Cache, Session Cursor Cache, JDBC Statement Cache가 각각 주로 줄이는 비용은 무엇인가?
정답 및 해설

Library Cache는 Shared SQL과 실행구조를 재사용해 Hard Parse를 줄이고, Session Cursor Cache는 같은 Session의 닫힌 Cursor 참조를 재사용해 실제 Reparse를 피하며, JDBC Statement Cache는 Physical Connection에서 Statement·Database Cursor 재생성과 반복 Prepare·통신을 줄입니다. 저장 위치와 재사용 단위가 다릅니다.

03Session Cursor가 Session Cursor Cache에 들어가기 위한 반복 기준은 무엇인가?
정답 및 해설

같은 Session에서 Cursor가 세 번 닫힌 뒤 Oracle이 반복 Statement로 판단하면 Session Cursor Cache에 들어갈 수 있습니다. 이후 항목은 LRU와 내부 Aging 정책에 따라 제거될 수 있습니다.

04Session Cursor Cache Hit가 발생해도 Parse Call 통계에 기록될 수 있는 이유는 무엇인가?
정답 및 해설

애플리케이션이 Parse 요청을 보냈다는 사실과 Database가 실제 Reparse 작업을 수행했다는 사실은 다르기 때문입니다. Cache된 Cursor 재사용은 Parse Call로 등록될 수 있지만 session cursor cache hits는 실제 Reparse가 불필요했던 횟수를 나타냅니다.

05SESSIONCACHEDCURSORS와 OPENCURSORS가 독립적인 이유는 무엇인가?
정답 및 해설

OPEN_CURSORS는 동시에 Open할 수 있는 Cursor 수이고 SESSION_CACHED_CURSORS는 닫힌 Session Cursor를 Cache하는 최대 수이기 때문입니다. Cached Session Cursor는 Open 상태가 아니므로 두 값은 독립적이고 Session Cache 값을 더 크게 설정할 수도 있습니다.

06V$SESSIONCURSORCACHE만으로 Parameter 효과를 판단하면 안 되는 이유는 무엇인가?
정답 및 해설

Oracle 공식 문서가 이 View를 SESSION_CACHED_CURSORS 효과 측정 수단이 아니라고 명시하기 때문입니다. V$SESSTAT의 Total Parse·Cache Hit·Cache Count Delta와 Application Trace, CPU·응답시간을 함께 비교해야 합니다.

07Oracle JDBC Implicit Statement Cache의 적용 대상과 대표 Matching 조건은 무엇인가?
정답 및 해설

Implicit Cache는 Prepared·Callable Statement에 적용되고 Plain Statement에는 적용되지 않습니다. SQL String의 대소문자 포함 동일성, Statement Type, Result Set Scroll Type이 대표 Matching 조건입니다.

08Connection Pool에서 Statement Cache 자원 총량을 계산할 때 고려할 요소는 무엇인가?
정답 및 해설

Physical Connection 수와 Connection당 Statement Cache Size의 곱, 각 Session의 Open Cursor 사용량, OPEN_CURSORS, Memory를 함께 봅니다. Cache는 Pool 전체 공유가 아니라 Physical Connection별로 존재합니다.

09VERSIONCOUNT가 높을 때 어떤 View와 정보를 추가로 확인해야 하는가?
정답 및 해설

V$SQL_SHARED_CURSOR에서 공유 실패 Flag를 확인하고 Bind 이름·Type·길이, Optimizer 환경, Object·권한, Invalidation, Adaptive Cursor Sharing 정보를 분석합니다. VERSION_COUNT는 현상이지 원인 자체가 아닙니다.

10Parse 비용 개선을 Application·Session·Library Cache 순서로 설명하시오.
정답 및 해설

먼저 SQL Text·Bind와 Prepared Statement 생명주기를 안정화해 Parse 요청 자체를 줄이고, 다음으로 Physical Connection별 JDBC Cache와 Session Cursor Cache의 Hit·자원을 조정하며, 마지막으로 Library Cache의 Hard Parse·Reload·Invalidation·Child Cursor 공유 실패 원인을 제거합니다. 모든 변경은 같은 부하의 Delta로 검증합니다.

정답 적용 체크

  • parse count (total)parse count (hard)를 같은 지표로 보지 않습니다.
  • Session Cursor Cache Hit는 Parse Call 통계와 실제 Reparse 작업을 구분해 해석합니다.
  • SESSION_CACHED_CURSORS는 세 번 닫힌 반복 Cursor의 Closed Cache이고 OPEN_CURSORS와 독립적입니다.
  • JDBC/UCP Statement Cache는 Physical Connection별이며 Prepared·Callable Statement를 중심으로 동작합니다.
  • V$SESSION_CURSOR_CACHE만으로 효과를 단정하지 않고 V$SESSTAT과 구간 Delta를 사용합니다.
  • V$OPEN_CURSOR는 Cursor Type을 구분하고 opened cursors current와 교차 검증합니다.
  • Cache 확대 전 SQL Text·Bind·Statement 생명주기와 Pool Connection 수를 먼저 확인합니다.