[6) I/O 효율화 원리] 7. Result 캐시

Yu River·2022년 5월 31일
0

Result 캐시

  • 오라클은 한번 수행한 쿼리 또는 PL/SQL 함수의 결과값을 Result 캐시에 저장해 두는 기능을 11g버전부터 제공하기 시작했다.
  • DML이 거의 발생하지 않는 테이블을 참조하면서, 반복 수행 요청이 많은 쿼리에 이 기능을 사용하면 I/O발생량을 현격히 감소시킬 수 있다.
  • Result Cache는 SGA영역에 존재하므로, 모든 세션에서 공유가능하고, 인스턴스를 재기동하면 초기화되며, 해당 쿼리가 접근하는 오브젝트가 변경될 때 invalid된다.
  • 공유영역에 존재하므로 래치가 필요하다.

[1] 배경

  • DB버퍼 캐시는 쿼리에서 자주 사용되는 블록들을 캐싱해 두는 메모리 공간이지만 캐싱된 블록을 읽는 것도 때에 따라서는 고비용 구조가 된다.
  • 반복 액세스가 많이 일어나거나 대용량 데이터 쿼리의 경우 버퍼 캐시 히트율이 낮으며 이에 대한 별다른 방안이 없다.

[2] Result Cache 영역 2가지

  • SQL Query Result 캐시 : SQL 쿼리 결과를 저장
  • PL/SQL 함수 Result 캐시 : PL/SQL 함수 결과값을 저장

[3] Result 캐시를 위해 추가된 파라미터들

(1) result_cache_mode

  • Result 캐시 등록 방식을 결정한다.
    • Manual (기본값) : result_cache 힌트를 명시한 SQL만 등록한다.
    • Force : no_result_cache 힌트를 명시하지 않은 모든 SQL을 등록한다.
    • Auto : 자주 사용되는 쿼리의 SQL을 등록한다.

(2) result_cache_max_size

  • SGA내에서 result_cache가 사용할 메모리 총량을 바이트로 지정한다.
  • 0으로 설정하면 이 기능이 작동하지 않는다.
  • memory_target의 0.25%, sga_target의 0.5%, shared_pool_size의 1%
    • 어떤 방식을 사용하든 최대크기는 shared pool의 75%를 넘지 않는다.
  • 기본값은 N/A 이다.

(3) result_cache_max_result

  • 하나의 SQL 결과집합이 전체 캐시 영역에서 차지할 수 있는 최대 크기%로 지정한다.
  • 기본값은 5이다.

(4) result_cache_remote_expiration

  • remote객체의 결과를 얼마 동안 보관할 지를 분 단위로 지정한다.
  • Remote 객체를 result 캐시에 저장하지 않도록 하려면 0으로 설정한다.
  • 기본값은 0이다.

[4] 파라미터 보기

SYS@YUHA >show parameter result

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
client_result_cache_lag big integer 3000
client_result_cache_size big integer 0
result_cache_max_result integer 5
result_cache_max_size big integer 3872K
result_cache_mode string MANUAL
result_cache_remote_expiration integer 0

[5] 사용방법(Manual 모드시) 예시

SELECT /*+ RESULT_CACHE */ COL, COUNT(*)
FROM R_CACHE_TEST
WHERE GUBUN = 7
GROUP BY COL;
  • result_cache 힌트를 사용하여 쿼리를 실행한다.
  • 오라클 서버 프로세스는 Result 캐시 메모리를 먼저 찾아보고 캐싱되어 있는 값이 있다면 그것을 가져다가 결과 집합을 리턴한다.(블록 I/O가 젼혀 발생하지 않는다.)
  • 쿼리 대/소 문자나 띄어쓰기가 틀리더라도 동일 SQL문으로 간주하여 등록되어 있는 result cache를 재사용한다.
  • 캐시에서 찾지 못할때만 쿼리를 수행해 결과를 리턴하고 result cache에도 저장해 둔다.
  • LRU 알고리즘에 의해 캐시되고 aging out 된다.

[6] 관련 사용 명령어

(1) SQL Result Cache 사용량 확인

set serveroutput on size 999999
execute dbms_result_cache.memory_report

(2) 전체 캐시 flush

begin
	bms_result_cache.flush;
end;

(3) 캐시내 하나의 테이블을 위한 캐시 flush

begin
	dbms_result_cache.invalidate('ARUP','CUSTOMERS');
end;

[7] mview 와의 차이점

  • 데이터를 메모리에 저장한다.
  • 인스턴스가 shutdown되거나 result_cache 공간이 다 사용되면 값이 사라진다.
  • 테이블 변경시 동적으로 변경이 일어난다.
  • 캐시된 이후에 오직 같은 쿼리나 query frangment가 다시 실행될 때에만 사용된다.

[8] 쿼리 결과집합을 Result Cache에 Caching하지 못하는 경우

  • Dictionary 오브젝트를 참조할 때
  • Temporary 테이블을 참조할 때
  • 시퀀스로부터 CURRVAL, NEXTVAL Pseudo 컬럼을 호출할 때
  • 쿼리에서 아래 SQL함수를 사용할 때
    • CURRENT_TIMESTAMP
    • LOCAL_TIMESTAMP
    • SYS_CONTEXT(with non-constant variables)
    • SYS_GUID
    • SYSDATE
    • SYSTIMESTAMP
    • USERENV(with non-constant variables)
    • CURRENT_DATE

[9] 쿼리 결과집합을 캐싱하지 않는 게 더 나은 경우

경우 1) 바인드 변수를 사용한 쿼리

  • 바인딩 되는 값에 따라 개별적으로 캐싱되므로, 변수값 종류가 다양한 쿼리는 등록을 삼가해야한다.
  • 즉 , 함수 또는 바인드 변수를 가진 쿼리에서 입력되는 값의 종류가 많고, 골고루 입력될 때는 사용을 자제한다.

경우 2) 쿼리에서 사용하는 테이블에 DML이 발생한 경우(결과 집합과 무관한 변경이라 하더라도)

  • 캐싱된 결과집합을 무효화 시킨다.
  • 즉 , 쿼리가 참조하는 테이블에 DML이 자주 발생할 때에는 사용을 자제한다.

예외 ) 인라인뷰 또는 일부집합만 캐싱도 가능하나 서브쿼리는 불가능하다.

[예시 1]

select *
from r_cache_test t1,
	( SELECT /*+ RESULT_CACHE */ ID
	  FROM R_CACHE_TEST2
	  WHERE ID = 1 ) T2
where t1.id = t2.id;

[예시 2]

select sum(val)
from (select sum(c) val
      from ext_stat_test
      union all
      SELECT /*+ RESULT_CACHE */ SUM(ID+SUM_DATA)
      FROM R_CACHE_TEST);

[예시 3]

select *
from r_cache_test
where id = (select /*+ result_cache */ id 
			from r_cache_test2
			where id = 1);

[10] ⭐️Result Chache 사용을 권장하는 경우⭐️

경우 1) 작은 결과 집합을 얻으려고 대용량 데이터를 읽어야 할 때

경우 2) 읽기 전용의 작은 테이블을 반복적으로 읽어야 할 때

경우 3) 읽기 전용코드 테이블을 읽어 코드명칭을 반환하는 함수

profile
도광양회(韜光養晦) ‘빛을 감추고 어둠속에서 힘을 기른다’

0개의 댓글