오라클 11g는 SGA뿐 아니라 PGA까지 포함하는 강력한 자동 메모리 관리(Automatic Memory Management:AMM) 기능을 제공한다.
앞으로는 오라클에 얼마만큼의 메모리를 써라~고 지정만 해주면 된다는 것을 의미한다. 멋진 일이긴 하지만, 실제 적용할 때는 염두에 두어야 할 몇가지 함정들이 있을 것이다.
간단해 보이지만, AMM의 속성을 잘 알 수 있는 Test Case를 만들어 보겠다.
- Memory Target, Memory Max Target 값을 200M로 설정한다.
- DB Cache와 Shared Pool 간의 경합을 시뮬레이션하기 위해, logical reads와 hard parse를 혼합해서 과도하게 발생시킨다.
- 이 상황에서, PGA aggregate target 의 변화가 발생하는지 체크한다.
*.memory_max_target=200m
declare
pat1 varchar2(1000);
pat2 varchar2(1000);
va number;
begin
select ksppstvl into pat1
from sys.xm$ksppi i, sys.xm$ksppcv v -- synonym of x$ table
where i.indx = v.indx
and i.ksppinm = '__pga_aggregate_target';
for idx in 1 .. 1000000 loop
-- Mixed workloads of heavy logical reads and hard parse
execute immediate
'select count(*) from t3 where 10 = mod('||idx||',10)+1' into va;
if mod(idx, 100) = 0 then
sys.dbms_system.ksdwrt(2, idx || 'th execution');
for p in (select ksppinm, ksppstvl
from sys.xm$ksppi i, sys.xm$ksppcv v
where i.indx = v.indx
and i.ksppinm in
('__shared_pool_size', '__db_cache_size',
'__pga_aggregate_target'))
loop
sys.dbms_system.ksdwrt(2, p.ksppinm || ' = ' || p.ksppstvl);
end loop;
select ksppstvl into pat2
from sys.xm$ksppi i, sys.xm$ksppcv v
where i.indx = v.indx
and i.ksppinm = '__pga_aggregate_target';
-- Do I have PGA aggregate target change?
if pat1 <> pat2 then
sys.dbms_system.ksdwrt(2, 'yep, I got it! pat1=' || pat1 ||', pat2='||pat2);
exit;
end if;
end if;
end loop;
end;
/
결과는 아래와 같다. (alert log 파일)
__shared_pool_size = 92274688
__db_cache_size = 16777216
__pga_aggregate_target = 83886080
200th execution
__shared_pool_size = 92274688
__db_cache_size = 16777216
__pga_aggregate_target = 83886080
300th execution
__shared_pool_size = 88080384
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
400th execution
__shared_pool_size = 92274688
__db_cache_size = 16777216
__pga_aggregate_target = 83886080
500th execution
__shared_pool_size = 88080384
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
600th execution
__shared_pool_size = 92274688
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
700th execution
__shared_pool_size = 92274688
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
800th execution
__shared_pool_size = 92274688
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
900th execution
__shared_pool_size = 92274688
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
1000th execution
__shared_pool_size = 92274688
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
1100th execution
__shared_pool_size = 92274688
__db_cache_size = 20971520
__pga_aggregate_target = 83886080
1200th execution
__shared_pool_size = 92274688
__db_cache_size = 37748736
__pga_aggregate_target = 58720256
yep, I got it! pat1=83886080, pat2=58720256
기대했던대로, Oracle은 부하에 따라 Buffer Cache의 크기와 Shared Pool의 크기를 주거니 받거니 하면서 변경하는 것을 볼 수 있다.
그런데, 1200번째 실행에서는 갑자기 PGA aggregate target 영역에서 메모리를 훔쳐서 Buffer Cache로 가져다쓴다. 이 역시 AMM(Automatic Memory Management)에서는 충분히 발생가능한 일이다.
문제는 어떤 특정 상황에서는 위험이 발생할 수 있다는 것이다. PGA aggregate target가 바뀐다는 것은 Hash/Sort관련 Operation의 Cost가 변경된다는 것을 의미한다. 따라서 갑자기 실행 계획이 바뀌는 것과 같은 위험한 상황이 발생 할 수도 있다. PGA Aggregate Target이 변하면 Hash/Sort의 성능 자체에도 영향을 주게 된다.
조금 극단적인 Test Case라고 할 수 있지만, 이런 현상이 논리적인 빈틈이나 버그로 인해 끔찍한 결과를 초래할 수 있다는 것은 경험으로 잘 알 고 있을 것이다.
오라클 11g가 좀 더 대중화되면, 이런 유형의 문제에 대한 실사례를 접할 수 있을 것이다.
'Oracle > Admin' 카테고리의 다른 글
파티션 테이블 인덱스 DDL 작업 (0) | 2015.08.18 |
---|---|
테이블의 move시에 인덱스는 어떻게 될까? (0) | 2015.04.30 |
SQL*Loader 성능을 향상시키는 방법 (0) | 2013.01.16 |
유저 단위 export시 테이블스페이스 관련 (0) | 2012.09.24 |
11g Diagnostic Pack / Tuning Pack (0) | 2012.09.18 |