현재 선택한 SQL 과정

SQLP 이론 학습

이론 목록으로 돌아가기

Scalar Subquery Cache·Result Cache·DETERMINISTIC: 재사용과 정확성

반복 계산을 줄이는 Scalar Subquery Cache, SQL·PL/SQL Result Cache와 DETERMINISTIC의 보장 범위를 비교합니다.

예상 읽기 27

핵심 요약

반복 계산을 줄이는 기능마다 Cache 범위와 정확성 보장이 다릅니다. 다음 네 가지를 분리해서 이해해야 합니다.

기능재사용 범위저장 대상핵심 판단
Scalar Subquery 실행 중 재사용한 SQL 실행 내부상관 Key에 대한 스칼라 결과반복 Key·충돌·실제 Starts
SQL Result Cache여러 실행·SessionSQL Query Block의 결과 집합작은 결과·낮은 변경률·Invalidation
PL/SQL Function Result Cache여러 실행·Session함수 인수별 반환값함수 의존 데이터·인수 다양성
DETERMINISTICCache 범위를 정의하지 않음같은 입력에 같은 결과라는 함수 속성 선언정확성 계약·부작용 금지

DETERMINISTIC은 함수의 의미적 속성을 선언하고, Result Cache는 계산 결과를 저장합니다. Result Cache를 사용해도 Eligibility·입력값·무효화·Memory·Blocklist·실행 횟수 조건에 따라 실제 재사용 범위가 달라집니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
재사용 대상은 무엇인가?
→ 상관 Key별 Scalar 값
→ SQL Query 결과
→ 함수 인수별 반환값

재사용 범위는 어디까지인가?
→ 현재 Statement
→ 여러 실행·Session

정확성을 누가 보장하는가?
→ Database Dependency 추적
→ 개발자의 DETERMINISTIC·Session State 계약

이 이론의 범위

SQLP SQL 고급 활용 및 튜닝 → 스칼라 서브쿼리 범위에서 Statement 내부 재사용, Server Result Cache, PL/SQL Function Result Cache, DETERMINISTIC, Invalidation·Bypass·진단 View를 다룹니다.

학습 목표

이 이론을 학습한 뒤에는 다음을 설명할 수 있어야 합니다.

  1. Scalar Subquery 실행 중 재사용과 Server Result Cache의 범위를 구분한다.
  2. SQL Result Cache와 PL/SQL Function Result Cache의 저장 대상을 비교한다.
  3. DETERMINISTIC의 의미와 Result Cache와의 차이를 설명한다.
  4. 반복 Key 수와 NDV가 Scalar Subquery 재사용 효과에 미치는 영향을 판단한다.
  5. 의존 Object 변경과 Session State가 Cache 정확성에 미치는 영향을 설명한다.
  6. Result Cache가 유리한 Query와 불리한 Query를 구분한다.
  7. RESULT_CACHE_MODE, RESULT_CACHE_INTEGRITY, Cache 활성 상태를 구분한다.
  8. Function Result Cache의 실행 Threshold와 Cache Hit 인수 비교 규칙을 설명한다.
  9. DML 중 Result Cache Bypass와 Commit 후 Invalidation을 구분한다.
  10. 실행계획과 Dynamic Performance View로 재사용 효과를 검증한다.

1. 먼저 구분해야 할 네 가지 개념

Scalar Subquery 실행 중 재사용

상관 스칼라 서브쿼리의 입력 Key가 반복될 때 Oracle은 한 Statement 실행 안에서 이미 계산한 결과를 내부적으로 재사용할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT o.order_id,
       (SELECT c.customer_name
        FROM   customer c
        WHERE  c.customer_id = o.customer_id) AS customer_name
FROM   orders o;

ORDERS의 여러 행이 같은 CUSTOMER_ID를 가지면 동일한 고객명 Lookup 결과를 다시 사용할 가능성이 있습니다.

이 재사용은 다음 특성을 가집니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
범위
→ 현재 SQL 실행 내부

Key
→ 상관 Column 값의 조합

효과
→ Subquery 또는 함수의 실제 실행 횟수 감소 가능

보장
→ 모든 반복 Key가 반드시 한 번만 계산되는 것은 아님

Cache 용량, Hash 충돌, Key 분포, Optimizer 변환에 따라 효과가 달라질 수 있으므로 고정된 Cache 크기나 적중률을 암기하지 않고 실제 통계로 확인합니다.

SQL Result Cache

SQL Query의 결과 행 집합을 Server Result Cache에 저장하고 동일한 Query가 다시 실행될 때 재사용하는 기능입니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT /*+ RESULT_CACHE */
       region_id,
       SUM(order_amount) AS total_amount
FROM   orders
GROUP BY region_id;

Cache Hit가 발생하면 Base Table을 다시 읽고 집계하는 작업 대신 저장된 결과를 사용할 수 있습니다.

PL/SQL Function Result Cache

함수의 입력 인수와 반환값을 Result Cache에 저장합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CREATE OR REPLACE FUNCTION get_exchange_rate(
    p_currency_code VARCHAR2
) RETURN NUMBER
RESULT_CACHE
IS
    l_rate NUMBER;
BEGIN
    SELECT exchange_rate
    INTO   l_rate
    FROM   exchange_rate_master
    WHERE  currency_code = p_currency_code;

    RETURN l_rate;
END;
/

동일한 인수로 함수를 다시 호출할 때 유효한 Cache Entry가 있으면 함수 본문 실행을 줄일 수 있습니다.

DETERMINISTIC

함수가 같은 입력값에 대해 항상 같은 결과를 반환하며 부작용을 만들지 않는다는 개발자의 선언입니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CREATE OR REPLACE FUNCTION normalize_code(
    p_code VARCHAR2
) RETURN VARCHAR2
DETERMINISTIC
IS
BEGIN
    RETURN UPPER(TRIM(p_code));
END;
/

이 선언은 함수의 의미적 속성을 나타냅니다. 별도의 Result Cache 저장 공간이나 Cache 생명주기를 정의하지 않습니다.


2. Scalar Subquery 재사용의 작동 조건

다음 데이터가 있다고 가정합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
ORDERS 1,000,000행
CUSTOMER_ID NDV 1,000

주문은 백만 건이지만 고객은 천 명이므로 같은 고객번호가 반복됩니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Outer 행 수 = 1,000,000
서로 다른 상관 Key = 1,000

이 경우 고객명 Lookup 결과를 실행 중 재사용할 기회가 많습니다.

반대로 다음과 같다면 재사용 가능성이 낮아집니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
ORDERS 1,000,000행
CUSTOMER_ID NDV 950,000

대부분의 행이 서로 다른 Key를 사용하므로 Cache Entry가 재사용되기 전에 새로운 Key가 계속 들어올 수 있습니다.

재사용 효과에 영향을 주는 요소

  • 바깥 Row Source의 행 수
  • 상관 Key의 NDV
  • 같은 Key가 나타나는 순서와 집중도
  • Cache Entry 충돌
  • Subquery 한 번의 비용
  • Optimizer의 Unnesting 여부
  • 일부 Fetch인지 전체 Fetch인지
  • Parallel Execution과 실행 구조

정렬로 Cache Hit를 높이는 접근

같은 상관 Key를 모아 처리하면 재사용 가능성이 높아질 수 있지만, 이를 위해 추가 Sort가 필요하면 전체 비용이 더 커질 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Key 정렬 비용
↕
Subquery 반복 감소 이득

Cache Hit만 높이기 위해 불필요한 ORDER BY를 추가하지 않고, Sort Workarea·TEMP와 전체 응답시간을 함께 비교합니다.


3. Scalar Subquery Cache를 직접 설정하는가

Scalar Subquery의 실행 중 재사용은 일반 SQL 문법으로 크기나 교체 정책을 직접 설정하는 사용자 관리 Cache와 구분됩니다.

다음과 같은 접근을 피합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Cache Bucket 수를 고정 상수로 암기
숨은 Parameter로 Cache 크기 변경
모든 반복 Key는 반드시 한 번만 실행된다고 가정

검증은 실제 Cursor 통계를 이용합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT /*+ GATHER_PLAN_STATISTICS */
       o.order_id,
       (SELECT c.customer_name
        FROM   customer c
        WHERE  c.customer_id = o.customer_id) AS customer_name
FROM   orders o;
SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT *
FROM TABLE(
    DBMS_XPLAN.DISPLAY_CURSOR(
        NULL,
        NULL,
        'ALLSTATS LAST +PREDICATE +ALIAS +NOTE'
    )
);

다음 값을 비교합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Outer A-Rows
상관 Key NDV
Subquery Starts
Inner A-Rows
Inner Buffers
전체 A-Time

예시 해석

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Outer A-Rows      = 100,000
상관 Key NDV      = 500
Subquery Starts   = 650

실제 Starts가 Outer 행 수보다 크게 작다면 실행 중 재사용이나 다른 최적화가 영향을 주었을 가능성을 검토할 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Outer A-Rows      = 100,000
Subquery Starts   = 100,000

반복 실행이 거의 그대로 발생했다면 Join·사전 집계·LATERAL 대안과 비교합니다.

실행계획의 Starts는 Row Source 시작 횟수이므로 내부 Cache Hit 전체를 단독으로 설명하지는 못합니다. 다음을 함께 사용합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Outer A-Rows
상관 Key NDV
Subquery Starts
Inner Buffers·A-Time
SQL Trace
함수 호출 Counter
전체 Fetch 범위

또한 Scalar Subquery 실행 중 재사용은 Server Result Cache의 V$RESULT_CACHE_OBJECTS에 사용자가 관리하는 Entry로 나타나는 기능과 구분합니다. Statement 종료 후 여러 Session이 공유하는 Cache라고 가정하지 않습니다.


4. SQL Result Cache의 범위

Server Result Cache는 Shared Pool 내부의 Result Cache Memory를 사용하며, SQL Query 결과를 여러 실행과 Session이 재사용할 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Session A가 Query 실행
→ Query 결과 생성
→ Result Cache 저장

Session B가 같은 결과를 요청
→ 유효한 Cache Entry 확인
→ 저장된 결과 재사용 가능

적합한 Query

  • 동일한 Query가 자주 반복됨
  • 많은 Base Row를 읽지만 결과는 작음
  • 집계·정렬 비용이 큼
  • 원본 데이터 변경이 드묾
  • Bind 값 조합의 종류가 제한적임
  • 여러 Session이 같은 결과를 반복 요청함

예를 들어 기준정보나 일별 마감 집계처럼 데이터 변경은 적고 조회는 많은 경우를 검토할 수 있습니다.

불리한 Query

  • 원본 Table에 DML이 매우 자주 발생함
  • 결과 집합이 큼
  • Bind 값 조합이 매우 다양함
  • Query가 한 번 또는 드물게 실행됨
  • Session별 상태나 현재 시간에 따라 결과가 달라짐
  • Cache 무효화와 재생성이 반복됨

의존 Object 변경

Cache 결과를 만든 Table이나 View의 데이터가 Commit된 변경으로 수정되면 관련 결과가 무효화될 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Query 결과 Cache
→ 의존 Table 변경·Commit
→ 관련 Cache Entry Invalidation
→ 다음 실행에서 재계산

DML이 빈번하면 Hit보다 Invalidation과 재생성 비용이 커질 수 있습니다.


4.1 Server Result Cache의 활성 상태와 정책

Server Result Cache는 Shared Pool 내부의 SQL Query Result Cache와 PL/SQL Function Result Cache가 공유하는 Memory 영역입니다.

주요 설정은 다음과 같습니다.

항목역할
RESULT_CACHE_MODESQL Query 결과를 Manual Hint 중심으로 사용할지, 가능한 Query에 Force할지 결정
RESULT_CACHE_MAX_SIZEServer Result Cache Memory 최대 크기
RESULT_CACHE_INTEGRITYResult Cache 적격성 판단에서 결정성 무결성 정책
RESULT_CACHE_MAX_RESULT단일 결과가 Memory Cache에서 차지할 수 있는 비율 관련 설정
RESULT_CACHE_EXECUTION_THRESHOLD함수와 특정 인수 조합이 Cache 대상이 되기 전 관찰 횟수

Cache 활성 여부는 Parameter 값만 보지 않고 다음처럼 확인할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT DBMS_RESULT_CACHE.STATUS()
FROM   dual;

Instance 시작 시 Result Cache가 비활성화된 경우, 일부 Parameter 값을 동적으로 바꿔도 재시작 전 실제 Cache 상태와 표시값이 다를 수 있으므로 DBMS_RESULT_CACHE.STATUS()를 확인합니다.

RESULT_CACHE_INTEGRITY 정책과 Query의 비결정적 요소에 따라 Hint가 있어도 Cache 적격성이 달라질 수 있습니다.


5. SQL Result Cache 사용 방법

대표적인 방법은 Query Block에 RESULT_CACHE Hint를 지정하는 것입니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT /*+ RESULT_CACHE */
       product_category,
       SUM(sales_amount) AS total_amount
FROM   sales
WHERE  sales_date >= DATE '2026-01-01'
GROUP BY product_category;

Cache 사용을 제외하려면 다음 Hint를 사용할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT /*+ NO_RESULT_CACHE */
       ...
FROM   ...;

Result Cache Hint는 지정된 Query Block의 결과에 적용됩니다. Inline View나 WITH Query에 지정할 때는 어느 Query Block의 결과를 재사용하려는지 확인해야 합니다.

최근 버전에서는 Hint Scope와 Temporary Result 사용 정책이 확장될 수 있으므로 운영 Version의 Hint 문법과 설정을 확인합니다. 결과가 Memory의 단일 결과 제한보다 큰 경우 Temp 유형 Result Cache Object가 Temporary Tablespace를 사용할 수 있으므로 “Result Cache는 항상 Memory-only”라고 단정하지 않습니다.

Hint가 있다고 반드시 Cache되는 것은 아니다

다음 조건에 따라 Cache Entry가 생성되거나 재사용되지 않을 수 있습니다.

  • Query가 Result Cache 제한 사항에 해당
  • Result Cache Memory 부족
  • 결과가 너무 큼
  • 의존 Object 상태 변경
  • 입력 Bind 값이 기존 Entry와 다름
  • Database 설정과 Hint 적용 범위
  • Cache Blocklist 또는 내부 정책

따라서 Hint 존재 여부보다 실제 실행계획과 Result Cache View를 확인합니다.


6. PL/SQL Function Result Cache

PL/SQL Function Result Cache는 다음 조합을 Key처럼 사용합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
함수 식별 정보
+ 입력 인수 값
→ 반환값

예를 들어 다음 호출은 서로 다른 Cache Entry 후보입니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
get_exchange_rate('USD')
get_exchange_rate('JPY')
get_exchange_rate('EUR')

Cache 생성 Threshold

Oracle AI Database 26ai의 PL/SQL Function Result Cache는 최근 호출 이력을 이용해 함수와 특정 인수 조합이 일정 횟수 관찰된 뒤 Cache할 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
RESULT_CACHE_EXECUTION_THRESHOLD = 2 예시

첫 호출
→ 함수 계산, 아직 Cache하지 않을 수 있음

둘째 호출
→ 함수 계산 후 Cache Entry 생성 후보

셋째 호출
→ 유효한 Entry가 있으면 재사용

따라서 첫 호출부터 반드시 Cache Hit가 발생한다고 가정하지 않습니다. Threshold는 운영 설정을 확인합니다.

Cache Hit의 인수 비교

Function Result Cache의 인수 비교는 PL/SQL의 일반 = 비교와 완전히 같지 않습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
NULL 인수
→ Cache Hit 비교에서는 NULL과 NULL이 같은 Key로 취급

Non-NULL Scalar
→ 값의 표현이 동일한지 엄격하게 비교
→ CHAR 'AA'와 'AA '가 별도 Entry가 될 수 있음

인수 정규화 방식과 데이터 타입이 Cache Entry 수에 영향을 줄 수 있습니다.

적합한 함수

  • 자주 호출됨
  • 계산 또는 Lookup 비용이 큼
  • 반환값이 작음
  • 인수 종류가 제한적임
  • 의존 데이터가 드물게 변경됨
  • Session State에 의존하지 않음

의존 데이터 추적

Result-Cached Function이 실행 중 조회한 Table과 View를 Database가 추적할 수 있습니다. 해당 데이터에 Commit된 변경이 발생하면 관련 Cache 결과가 무효화됩니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
함수 결과 Cache
→ 함수가 참조한 기준 Table 변경
→ Cache Entry Invalidation
→ 다음 호출에서 함수 재실행

주의할 외부 상태

다음 값에 결과가 의존하면 Cache 정확성을 별도로 검토해야 합니다.

  • SYSDATE, SYSTIMESTAMP
  • Sequence
  • Package Global Variable
  • SYS_CONTEXT
  • Session NLS 설정
  • 애플리케이션 Context
  • 외부 File·Network 상태
  • Commit되지 않은 Session별 상태

Database가 추적하지 못하는 상태가 반환값에 영향을 주면 유효하지 않은 결과가 재사용될 수 있습니다.

DML 중 Cache Bypass

한 Session이 Result-Cached Function이 의존하는 Table에 DML을 수행 중이면 해당 Session은 Transaction이 Commit 또는 Rollback될 때까지 Cache를 우회할 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Session A
→ 기준 Table UPDATE
→ 자신의 미Commit 변경을 보아야 함
→ 관련 Function Result Cache Bypass
→ 함수 직접 계산
→ 계산 결과도 Cache에 저장하지 않음

이 동작은 Session 자신의 미Commit 변경을 다른 Session의 공유 Cache 결과와 혼동하지 않게 합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Commit
→ 의존 Cache Entry Invalidation 가능

Rollback
→ 공유 Cache의 기존 Committed 결과 사용 재개 가능

Bypass와 Invalidation은 서로 다른 시점과 목적의 동작입니다.


7. DETERMINISTIC의 정확한 의미

DETERMINISTIC 함수는 다음 규칙을 만족해야 합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
같은 입력 인수
→ 같은 반환값

호출 과정
→ 외부 상태를 변경하는 부작용 없음
→ 처리되지 않은 예외를 발생시키지 않음

예를 들어 문자열을 정규화하는 순수 함수는 적합할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CREATE OR REPLACE FUNCTION canonical_email(
    p_email VARCHAR2
) RETURN VARCHAR2
DETERMINISTIC
IS
BEGIN
    RETURN LOWER(TRIM(p_email));
END;
/

다음 함수는 현재 시간에 따라 결과가 바뀌므로 같은 입력에 같은 결과를 보장하지 못합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
CREATE OR REPLACE FUNCTION make_token(
    p_id NUMBER
) RETURN VARCHAR2
DETERMINISTIC
IS
BEGIN
    RETURN p_id || ':' || TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS');
END;
/

선언을 Database가 완전히 검증하지 않는다

DETERMINISTIC은 개발자가 의미적 규칙을 지킨다는 선언입니다. 함수 구현이 규칙을 위반해도 Compiler·SQL Engine·PL/SQL Engine이 문제를 진단하지 않을 수 있으며, Oracle 공식 의미상 Invocation 결과와 호출자에 미치는 영향이 정의되지 않은 상태가 될 수 있습니다.

따라서 단순히 성능을 위해 거짓으로 DETERMINISTIC을 선언하면 안 됩니다.

사용되는 대표 위치

PL/SQL 함수를 다음 구조에서 사용하려면 DETERMINISTIC 속성이 중요합니다.

  • Function-Based Index
  • PL/SQL 함수를 사용하는 Virtual Column
  • Query Rewrite 또는 Fast Refresh와 관련된 Materialized View 표현식

함수 구현이 변경되면 종속된 Function-Based Index나 Materialized View는 자동으로 새 함수 의미에 맞게 재작성된다고 가정하지 않습니다. 관련 Function-Based Index와 Materialized View를 수동으로 Rebuild·Refresh하고 결과를 재검증합니다.


8. DETERMINISTIC과 RESULT_CACHE 비교

항목DETERMINISTICRESULT_CACHE
핵심 목적함수의 의미적 성질 선언함수 결과를 Cache에 저장
저장 공간별도 Cache를 정의하지 않음Server Result Cache 사용
같은 입력같은 결과를 반환해야 함같은 인수 Entry를 재사용 가능
의존 데이터 변경자동 Cache Invalidation 개념이 핵심이 아님추적된 의존 Object 변경 시 무효화
정확성 책임개발자 선언의 정확성이 핵심Cache 대상·Dependency·추적되지 않는 상태 검토
첫 호출별도 Cache 생성 규칙을 정의하지 않음Threshold·Memory·Eligibility에 따라 함수 본문 실행 가능
DML 중Cache Bypass 개념과 별개의존 Table DML Session은 Cache를 우회할 수 있음
주요 사용FBI·Virtual Column·Query Rewrite 등반복 Function 호출 비용 감소

DETERMINISTIC 함수도 매 호출이 Result Cache에서 반환된다고 보장되지 않습니다.

RESULT_CACHE 함수는 Session State에 따라 달라지는 값을 저장할 때 정확성 위험이 생길 수 있습니다.

두 속성은 서로 대체 관계가 아니라 목적이 다른 기능입니다.


9. 스칼라 서브쿼리와 PL/SQL 함수 호출

SQL에서 PL/SQL 함수를 행마다 호출하면 다음 비용이 생길 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
SQL Engine
→ PL/SQL Function 호출
→ 함수 내부 SQL 실행
→ 결과 반환

Outer 행이 많으면 Engine 전환과 함수 내부 SQL이 반복됩니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT o.order_id,
       get_customer_grade(o.customer_id) AS customer_grade
FROM   orders o;

함수 호출을 스칼라 서브쿼리 안에 배치하면 반복 Key 결과의 실행 중 재사용 기회를 얻는 경우가 있지만, 이는 보장된 일반 해법으로 사용하지 않습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT o.order_id,
       (SELECT get_customer_grade(o.customer_id)
        FROM   dual) AS customer_grade
FROM   orders o;

다음 대안을 우선 비교합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
함수 내부 SQL을 Join으로 전개
기준 Table을 직접 Join
사전 집계
PL/SQL RESULT_CACHE
Statement 내부 Scalar 재사용

정확한 결과 의미와 전체 실행 비용을 실측한 뒤 선택합니다.

SQL에서 호출되는 PL/SQL 함수는 SQL Engine과 PL/SQL Engine 사이의 전환 비용이 누적될 수 있습니다. PRAGMA UDF 등 호출 오버헤드 완화 기능이 있더라도 함수 내부의 반복 SQL과 데이터 접근량을 자동 제거하는 것은 아니므로 Join·집합 처리 대안과 비교합니다.


10. Result Cache 진단 도구

Cache Object 확인

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT type,
       status,
       name,
       namespace,
       block_count,
       scan_count
FROM   v$result_cache_objects
ORDER BY type, name;

주요 해석은 다음과 같습니다.

항목의미
TYPEResult·Dependency·Temp Object 유형
STATUSCache Object 상태
NAMESPACESQL·PLSQL·KEY VECTOR 등 구분
BLOCK_COUNT사용한 Cache Block
SCAN_COUNT재사용된 횟수를 판단하는 참고값

Database 버전에 따라 View Column이 달라질 수 있으므로 현재 Version의 Data Dictionary를 확인합니다.

STATUSNew, Published, Bypass, Expired, Invalid 등 Cache Object의 현재 상태를 보여 줄 수 있습니다. SCAN_COUNT가 0인 Result가 대량으로 누적되면 Entry를 만들었지만 재사용하지 못한 패턴인지 점검합니다.

전체 Statistics 확인

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT id,
       name,
       value
FROM   v$result_cache_statistics
ORDER BY id;

Memory Report

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SET SERVEROUTPUT ON

BEGIN
    DBMS_RESULT_CACHE.MEMORY_REPORT;
END;
/

실행계획 확인

Result Cache를 사용하는 Query는 실행계획에서 Result Cache 관련 Row Source나 Note를 확인할 수 있습니다. 다음도 함께 비교합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
첫 실행과 두 번째 실행의 Buffers·A-Time
Cache Hit 여부
의존 Object 변경 후 재실행
서로 다른 Bind 값의 Entry 수
Cache Object의 크기와 재사용 횟수

11. Cache 사용 전후 검증 시나리오

1단계: 기준 실행

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Cache를 사용하지 않은 실행
→ Elapsed Time
→ CPU
→ Buffers
→ Reads
→ 반환 Row 수

2단계: 첫 Cache 생성 실행

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Query 실제 수행
→ 결과 생성
→ Cache Entry 저장 가능

첫 실행은 Cache 생성 비용까지 포함하므로 Hit 실행과 분리합니다.

3단계: 동일 입력 반복 실행

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
동일 SQL 또는 함수
동일 Bind·인수
동일 Session 상태
의존 데이터 변경 없음

Function Result Cache는 RESULT_CACHE_EXECUTION_THRESHOLD 때문에 두 번째 실행까지 함수 본문이 실행되고 이후에 Hit가 나타날 수 있으므로 최소 3회 이상 반복해 관찰합니다.

4단계: 다른 입력

Bind 값이나 함수 인수를 바꾸어 Entry가 분리되는지 확인합니다.

5단계: 의존 데이터 변경과 Transaction

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
DML 전 Hit 실행
→ 같은 Session에서 의존 Table DML
→ Commit 전 Cache Bypass·자기 변경 가시성 확인
→ Commit
→ 관련 Entry Invalidation 확인
→ 다음 실행 재계산

Rollback 경로도 별도로 확인합니다.

6단계: 동시 실행

여러 Session에서 Hit Rate뿐 아니라 Shared Pool 경합과 전체 처리량을 확인합니다.


12. Result Cache가 유리한지 판단하는 공식

정확한 비용은 환경마다 다르지만 다음 구조로 생각할 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Cache 이득
≈ 반복 실행 횟수 × 원래 계산 비용
 - Cache Lookup 비용
 - Cache 생성 비용
 - Invalidation·재생성 비용
 - Result Cache Memory·TEMP 비용
 - Threshold 도달 전 실행 비용

유리한 패턴

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
계산 비용 큼
반복 횟수 많음
결과 작음
입력 종류 적음
원본 변경 적음

불리한 패턴

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
계산 비용 작음
반복 횟수 적음
결과 큼
입력 종류 많음
원본 변경 많음
Session별 결과 차이 큼

Cache Hit Ratio만 높고 원래 Query가 매우 가볍다면 전체 성능 개선은 작을 수 있습니다. 반대로 Hit Ratio가 완벽하지 않아도 매우 비싼 Query를 반복해서 피하면 효과가 클 수 있습니다.


혼동하기 쉬운 판단

혼동하기 쉬운 판단정확한 기준
Scalar Subquery Cache는 모든 Session이 공유한다현재 Statement 실행 내부의 재사용으로 이해한다
반복 Key는 항상 한 번만 계산된다Cache 충돌·Key 분포·변환에 따라 실제 Starts가 달라진다
RESULT_CACHE Hint가 있으면 반드시 Cache Hit가 난다Eligibility·Memory·Bind·Invalidation·설정을 확인한다
Result Cache는 DML이 많을수록 최신 결과를 빠르게 준다DML이 많으면 Invalidation과 재생성이 반복될 수 있다
DETERMINISTIC은 자동 Result Cache다같은 입력에 같은 결과를 보장한다는 함수 속성 선언이다
DETERMINISTIC 위반은 항상 오류로 발견된다Compile·실행에서 진단되지 않고 잘못된 결과가 생길 수 있다
PL/SQL Result Cache는 모든 외부 상태를 추적한다추적되지 않는 Session·시간·외부 상태를 개발자가 검토해야 한다
Cache Hit Ratio만 높으면 성공이다원래 계산 비용·Memory·Invalidation·전체 처리량을 함께 본다
Function Result Cache는 첫 호출부터 저장·HitExecution Threshold에 따라 여러 호출 후 Cache될 수 있다
Result Cache 인수 비교는 PL/SQL =와 완전히 같다NULL·CHAR 등 Cache Key 비교 규칙이 더 엄격할 수 있다
Result Cache는 항상 Shared Pool Memory만 사용큰 결과는 Version·설정에 따라 Temp Object가 될 수 있다
DML 중에도 항상 기존 Function Cache를 읽는다자신의 미Commit 변경을 위해 Cache Bypass가 발생할 수 있다
DETERMINISTIC 함수는 예외를 발생시켜도 된다처리되지 않은 예외도 의미 규칙을 위반한다
함수 수정 후 FBI가 자동으로 새 의미를 반영종속 FBI·MV를 수동 Rebuild·Refresh하고 검증한다

핵심 판단 순서

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
반복되는 것은 Query 결과인가, 함수 결과인가, 상관 Key 결과인가?
→ 필요한 재사용 범위는 한 실행인가, 여러 실행·Session인가?
→ Cache가 실제 ENABLED인가?
→ RESULT_CACHE_MODE·INTEGRITY·EXECUTION_THRESHOLD는 무엇인가?
→ 입력 Key·Bind·함수 인수의 NDV와 표현은 얼마인가?
→ 결과 크기와 원래 계산 비용은 얼마인가?
→ Memory 결과인가 Temp Object 가능성이 있는가?
→ 의존 데이터는 얼마나 자주 변경되는가?
→ DML 중 Bypass와 Commit 후 Invalidation은 어떻게 발생하는가?
→ Session State·시간·Sequence·외부 상태에 따라 결과가 달라지는가?
→ DETERMINISTIC 의미 규칙을 실제로 만족하는가?
→ 실제 Starts·Buffers·Cache Object·Statistics로 효과를 검증했는가?
스스로 확인하기

개념 확인 문제

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

01Scalar Subquery 실행 중 재사용과 SQL Result Cache의 가장 큰 범위 차이는 무엇인가?
정답 및 해설

Scalar Subquery 실행 중 재사용은 현재 SQL Statement 내부의 반복 상관 Key 결과를 대상으로 하고, SQL Result Cache는 Query 결과를 여러 실행·Session에서 재사용할 수 있습니다.

02상관 Key의 NDV가 매우 클 때 Scalar Subquery 재사용 효과가 작아질 수 있는 이유는 무엇인가?
정답 및 해설

상관 Key NDV가 Outer Row 수에 가까우면 이미 계산한 Key가 다시 나타날 기회가 적고 Cache 충돌·교체 가능성이 커집니다.

03SQL Result Cache에 적합한 Query의 대표적인 특징 세 가지는 무엇인가?
정답 및 해설

많은 Base Row를 읽지만 결과는 작고, 반복 실행이 많고, Bind 종류가 제한적이며, 의존 데이터 변경이 드문 Query가 SQL Result Cache 후보입니다.

04의존 Table에 Commit된 변경이 발생하면 SQL·PL/SQL Result Cache에 어떤 일이 생길 수 있는가?
정답 및 해설

의존 Object의 Commit 변경은 관련 SQL·PL/SQL Result Cache Entry를 Invalid 상태로 만들 수 있고 다음 실행에서 재계산하게 합니다.

05PL/SQL Function Result Cache는 무엇을 기준으로 결과를 구분하는가?
정답 및 해설

PL/SQL Function Result Cache는 함수 식별 정보와 입력 인수 값의 조합으로 Entry를 구분합니다. NULL·CHAR 등 Cache Hit 비교는 일반 PL/SQL =와 다를 수 있습니다.

06DETERMINISTIC 함수가 만족해야 하는 핵심 규칙 두 가지는 무엇인가?
정답 및 해설

DETERMINISTIC 함수는 같은 인수에 같은 값을 반환하고, 부작용이 없으며, 처리되지 않은 예외를 발생시키지 않아야 합니다.

07DETERMINISTIC을 잘못 선언했을 때 특히 위험한 이유는 무엇인가?
정답 및 해설

DETERMINISTIC은 Database가 완전히 검증하는 보증이 아니라 개발자의 Assertion입니다. 위반하면 오류 없이 잘못된 값이나 정의되지 않은 결과가 생길 수 있습니다.

08SYSDATE, Sequence, Package Variable에 의존하는 함수가 Cache에 부적합할 수 있는 이유는 무엇인가?
정답 및 해설

SYSDATE·Sequence·Package Variable·SYS_CONTEXT·NLS·외부 상태는 같은 명시적 인수에서도 결과를 바꿀 수 있고 Dependency 추적 대상이 아닐 수 있습니다.

09Result Cache 효과를 검증할 때 첫 실행과 두 번째 실행을 분리해야 하는 이유는 무엇인가?
정답 및 해설

첫 실행은 계산 비용과 Cache 생성 비용을 포함하고, Function Result Cache는 Execution Threshold 때문에 여러 번 실행된 뒤 Hit가 나타날 수 있으므로 생성 실행과 Hit 실행을 분리해야 합니다.

10Scalar Subquery·SQL Result Cache·PL/SQL Result Cache·DETERMINISTIC 중 어떤 기능을 선택할지 판단하는 첫 질문은 무엇인가?
정답 및 해설

먼저 재사용하려는 대상과 범위를 확정합니다. Statement 내부 상관 Key인지, SQL 결과인지, 함수 인수별 결과인지에 따라 Scalar 재사용·SQL Result Cache·Function Result Cache를 선택하고 DETERMINISTIC은 별도의 정확성 선언으로 판단합니다.