프린트 하기

OS 환경 : Oracle Linux 8.1 (64bit)

 

DB 환경 : Oracle Database 19.3.0.0

 

방법 : 오라클 19c 오브젝트 100만개 생성 및 shared pool 확인 테스트

오라클에서 테이블이나 인덱스 등의 용량을 차지하는 object이자 segment임
하지만 프로시저, 함수, 뷰 등은 용량을 차지하지 않는 object임(segment가 아님)
그래서 이 오브젝트들은 디스크가 아닌 메모리 상에, 정확히는 library cache에 상주하게 되는데
만약 적은 library cache에 아주 많은 오브젝트들을 생성하게되면 어떻게 되는지 궁금해서 테스트해봄
본문에서는 sga와 shared_pool_size를 작게 설정한 상태에서 많은 프로시저, 함수, 뷰 등의 오브젝트를 많이 생성한뒤 영향도를 확인하는 테스트를 진행해봄

 

 

테스트
사전 환경 구성
sga_target, shared_pool_size 크기를 최소한으로 조정

1
2
3
4
5
SQL>
alter system set sga_target = 300m scope=spfile;
alter system set shared_pool_size = 240m scope=spfile;
shutdown immediate;
startup;

 

 

system 데이터파일 5g로 resize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SQL> 
set lines 200 pages 1000
col tablespace_name for a20
col file_name for a70
select tablespace_name, file_id, file_name, round(bytes/1024/1024/1024, 2) gb,
round(maxbytes/1024/1024/1024, 2) max_gb, autoextensible, status, online_status from dba_data_files
union all
select tablespace_name, file_id, file_name, round(bytes/1024/1024/1024, 2) gb,
round(maxbytes/1024/1024/1024, 2) max_gb, autoextensible, status, null from dba_temp_files order by 2;
 
TABLESPACE_NAME         FILE_ID FILE_NAME                                                                      GB     MAX_GB AUT STATUS    ONLINE_
-------------------- ---------- ---------------------------------------------------------------------- ---------- ---------- --- --------- -------
SYSTEM                        1 /oradata1/ORACLE19/system01.dbf                                                 1          0 NO  AVAILABLE SYSTEM
TEMP                          1 /oradata1/ORACLE19/temp01.dbf                                                 .03         32 YES ONLINE
SYSAUX                        3 /oradata1/ORACLE19/sysaux01.dbf                                                 1          0 NO  AVAILABLE ONLINE
UNDOTBS1                      4 /oradata1/ORACLE19/undotbs01.dbf                                                1          0 NO  AVAILABLE ONLINE
IMSITS                        5 /oradata1/ORACLE19/imsits01.dbf                                                 2          0 NO  AVAILABLE ONLINE
USERS                         7 /oradata1/ORACLE19/users01.dbf                                                  1          0 NO  AVAILABLE ONLINE
 
6 rows selected.
 
SQL> alter database datafile 1 resize 5g;
 
Database altered.

오브젝트들이 system ts에 쌓이기 때문에 5gb로 증가시켜줌

 

 

기존 오브젝트 갯수 확인

1
2
3
4
5
6
7
8
9
SQL> 
set timing on
select count(*) from dba_objects;
 
  COUNT(*)
----------
     72367
 
Elapsed: 00:00:00.07

 

 

현재 용량이 가장큰 오브젝트 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SQL>
set lines 200 pages 1000
col tablespace_name for a20
col segment_name for a40
col segment_type for a20
select * from 
 (select tablespace_name, segment_name, segment_type, bytes/1024/1024 mb 
  from dba_segments 
  where tablespace_name in ('SYSTEM', 'SYSAUX') 
  order by 4 desc)
where rownum <= 10;
 
TABLESPACE_NAME      SEGMENT_NAME                             SEGMENT_TYPE                 MB
-------------------- ---------------------------------------- -------------------- ----------
SYSTEM               IDL_UB1$                                 TABLE                       392
SYSAUX               SYS_LOB0000064076C00006$$                LOBSEGMENT              72.1875
SYSAUX               SYS_LOB0000072914C00006$$                LOBSEGMENT              72.1875
SYSTEM               C_TOID_VERSION#                          CLUSTER                      48
SYSAUX               SYS_LOB0000007422C00004$$                LOBSEGMENT              40.1875
SYSTEM               SOURCE$                                  TABLE                        38
SYSTEM               IDL_UB2$                                 TABLE                        30
SYSAUX               SYS_LOB0000066421C00004$$                LOBSEGMENT              24.1875
SYSTEM               JAVA$MC$                                 TABLE                        21
SYSAUX               SYS_LOB0000067342C00002$$                LOBSEGMENT              16.1875
 
10 rows selected.

 

 

현재 shared pool 메모리 사용량 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SQL> 
select * from (
select name, bytes/1024/1024 as size_mb 
from v$sgastat 
where pool = 'shared pool' 
order by 2 desc)
where rownum <= 10;
 
NAME                          SIZE_MB
-------------------------- ----------
SQLA                       19.6125336
free memory                13.4635162
ksunfy_meta 1              12.8199463
KGLH0                      12.1591263
row cache mutex            8.60121918
ASH buffers                         8
KGLS                       7.40318298
SO private sga             7.29341888
private strands            7.14355469
row cache hash             5.73414612
 
10 rows selected.

 

 

사용량 sum 해서 확인

1
2
3
4
5
SQL> select sum(bytes/1024/1024) as size_mb from v$sgastat where pool = 'shared pool';
 
   SIZE_MB
----------
       240

shared_pool_sized와 동일한 240mb임

 

 

sga 영역별 크기 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SQL>
select component, current_size/1024/1024 as size_mb
from v$sga_dynamic_components;
 
COMPONENT                                                           SIZE_MB
---------------------------------------------------------------- ----------
shared pool                                                             240
large pool                                                                4
java pool                                                                 0
streams pool                                                              0
unified pga pool                                                          0
memoptimize buffer cache                                                  0
DEFAULT buffer cache                                                     36
KEEP buffer cache                                                         0
RECYCLE buffer cache                                                      0
DEFAULT 2K buffer cache                                                   0
DEFAULT 4K buffer cache                                                   0
DEFAULT 8K buffer cache                                                   0
DEFAULT 16K buffer cache                                                  0
DEFAULT 32K buffer cache                                                  0
Shared IO Pool                                                            4
Data Transfer Cache                                                       0
In-Memory Area                                                            0
In Memory RW Extension Area                                               0
In Memory RO Extension Area                                               0
ASM Buffer Cache                                                          0
 
20 rows selected.

현재 shared pool이 240mb, DEFAULT buffer cache가 36mb, Shared IO Pool이 4mb 할당되어 있음

 

 

파싱 카운트 확인

1
2
3
4
5
6
7
8
9
10
11
SQL>
set lines 200 pages 1000
col name for a30
select name, value
from v$sysstat
where name in ('parse count (total)', 'parse count (hard)');
 
NAME                                VALUE
------------------------------ ----------
parse count (total)                 19897
parse count (hard)                   3465

 

 

v$sql에 sql이 몇개 저장되는지 확인을 위해 쿼리 수행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL>
set timing on
DECLARE
    v_sql VARCHAR2(200);
BEGIN
    FOR i IN 1..10000 LOOP
        v_sql := 'SELECT /* test2025_01 */ COUNT(*) FROM DBA_OBJECTS WHERE OBJECT_ID = ' || TRUNC(DBMS_RANDOM.VALUE(1, 100000));
        EXECUTE IMMEDIATE v_sql;
    END LOOP;
END;
/
 
PL/SQL procedure successfully completed.
Elapsed: 00:01:20.45

 

 

위 sql 수행 직후 파싱 카운트 확인

1
2
3
4
5
6
7
8
9
10
11
SQL>
set lines 200 pages 1000
col name for a30
select name, value
from v$sysstat
where name in ('parse count (total)', 'parse count (hard)');
 
NAME                                VALUE
------------------------------ ----------
parse count (total)                 50643
parse count (hard)                  13834

 

 

파싱 카운트 계산

1
2
3
4
5
SQL> select 50643-19897 "total", 13834-3465 "hard" from dual;
 
     total       hard
---------- ----------
     30746      10369

1만회 pl/sql 수행시 각각 total : 30746, hard : 10369 증가함
내부적으로 시스템 sql도 실행되어 수치가 조금더 큰듯함

 

 

위 sql 수행 직후 v$sql의 총 sql 갯수 및 테스트 sql 갯수 확인

1
2
3
4
5
6
7
8
9
SQL> 
select 'all sql', count(*) from v$sql
union all
select 'test sql', count(*) from v$sql where sql_text like '%SELECT /* test2025_01 */%';
 
'ALLSQL'   COUNT(*)
-------- ----------
all sql         400
test sql        164

v$sql에 총 400개 sql이 존재하고 test sql은 164개 존재함

 

 

대량 오브젝트 생성용 스크립트 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$ cat create_objects.sh
#!/bin/bash
 
# 오브젝트 타입 설정 (procedure, function, view)
OBJECT_TYPE=$1
 
# 시작 ID 설정 (각 스크립트별 100000씩 증가)
START_ID=$2
END_ID=$((START_ID + 99999))
 
# 오라클 환경 변수 (필요시 수정)
ORACLE_HOME=/ORA19/app/oracle/product/19.0.0/db_1
ORACLE_SID=oracle19
PATH=$ORACLE_HOME/bin:$PATH
export ORACLE_HOME ORACLE_SID PATH
 
# SQL*Plus 실행하여 오브젝트 생성
sqlplus -s / as sysdba <<EOF
SET SERVEROUTPUT ON
WHENEVER SQLERROR EXIT SQL.SQLCODE
 
DECLARE
    v_sql VARCHAR2(4000);
    i NUMBER;
BEGIN
    FOR i IN $START_ID..$END_ID LOOP
        v_sql := CASE '$OBJECT_TYPE'
            WHEN 'procedure' THEN 'CREATE OR REPLACE PROCEDURE test_proc_' || i || ' AS BEGIN NULL; END;'
            WHEN 'function' THEN 'CREATE OR REPLACE FUNCTION test_func_' || i || ' RETURN NUMBER AS BEGIN RETURN ' || i || '; END;'
            WHEN 'view' THEN 'CREATE OR REPLACE VIEW test_view_' || i || ' AS SELECT ' || i || ' AS dummy FROM dual'
        END;
 
        EXECUTE IMMEDIATE v_sql;
    END LOOP;
END;
/
EXIT
EOF

 

 

스크립트 파일에 권한 부여

1
$ chmod u+c create_objects.sh

 

 

스크립트 nohub로 실행
(원래는 100만개씩 생성하려했지만 너무 느려 40,30,30만개 해서 총 100만개만 생성함)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$
# 프로시저 생성 (4개 세션)
nohup ./create_objects.sh procedure 1 > proc1.log 2>&1 &
nohup ./create_objects.sh procedure 100001 > proc2.log 2>&1 &
nohup ./create_objects.sh procedure 200001 > proc3.log 2>&1 &
nohup ./create_objects.sh procedure 300001 > proc4.log 2>&1 &
#nohup ./create_objects.sh procedure 400001 > proc5.log 2>&1 &
#nohup ./create_objects.sh procedure 500001 > proc6.log 2>&1 &
#nohup ./create_objects.sh procedure 600001 > proc7.log 2>&1 &
#nohup ./create_objects.sh procedure 700001 > proc8.log 2>&1 &
#nohup ./create_objects.sh procedure 800001 > proc9.log 2>&1 &
#nohup ./create_objects.sh procedure 900001 > proc10.log 2>&1 &
 
# 함수 생성 (3개 세션)
nohup ./create_objects.sh function 1 > func1.log 2>&1 &
nohup ./create_objects.sh function 100001 > func2.log 2>&1 &
nohup ./create_objects.sh function 200001 > func3.log 2>&1 &
#nohup ./create_objects.sh function 300001 > func4.log 2>&1 &
#nohup ./create_objects.sh function 400001 > func5.log 2>&1 &
#nohup ./create_objects.sh function 500001 > func6.log 2>&1 &
#nohup ./create_objects.sh function 600001 > func7.log 2>&1 &
#nohup ./create_objects.sh function 700001 > func8.log 2>&1 &
#nohup ./create_objects.sh function 800001 > func9.log 2>&1 &
#nohup ./create_objects.sh function 900001 > func10.log 2>&1 &
 
# 뷰 생성 (3개 세션)
nohup ./create_objects.sh view 1 > view1.log 2>&1 &
nohup ./create_objects.sh view 100001 > view2.log 2>&1 &
nohup ./create_objects.sh view 200001 > view3.log 2>&1 &
#nohup ./create_objects.sh view 300001 > view4.log 2>&1 &
#nohup ./create_objects.sh view 400001 > view5.log 2>&1 &
#nohup ./create_objects.sh view 500001 > view6.log 2>&1 &
#nohup ./create_objects.sh view 600001 > view7.log 2>&1 &
#nohup ./create_objects.sh view 700001 > view8.log 2>&1 &
#nohup ./create_objects.sh view 800001 > view9.log 2>&1 &
#nohup ./create_objects.sh view 900001 > view10.log 2>&1 &

 

 

실행중인 job들을 jobs 명령으로 확인

1
2
3
4
5
6
7
8
9
10
11
$ jobs -l
[1]  3148796 Running                 nohup ./create_objects.sh procedure 1 > proc1.log 2>&1 &
[2]  3148797 Running                 nohup ./create_objects.sh procedure 100001 > proc2.log 2>&1 &
[3]  3148798 Running                 nohup ./create_objects.sh procedure 200001 > proc3.log 2>&1 &
[4]  3148799 Running                 nohup ./create_objects.sh procedure 300001 > proc4.log 2>&1 &
[5]  3148802 Running                 nohup ./create_objects.sh function 1 > func1.log 2>&1 &
[6]  3148803 Running                 nohup ./create_objects.sh function 100001 > func2.log 2>&1 &
[7]  3148805 Running                 nohup ./create_objects.sh function 200001 > func3.log 2>&1 &
[8]  3148806 Running                 nohup ./create_objects.sh view 1 > view1.log 2>&1 &
[9]- 3148808 Running                 nohup ./create_objects.sh view 100001 > view2.log 2>&1 &
[10]+ 3148809 Running                 nohup ./create_objects.sh view 200001 > view3.log 2>&1 &

 

 

실행중인 job들을 top 명령으로 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ top
top - 15:38:12 up 4 days, 22:55,  4 users,  load average: 3.76, 2.12, 3.35
Tasks: 387 total,   8 running, 379 sleeping,   0 stopped,   0 zombie
%Cpu(s): 59.7 us, 14.3 sy,  0.0 ni, 21.6 id,  2.0 wa,  1.7 hi,  0.8 si,  0.0 st
MiB Mem :   7937.9 total,    113.4 free,   1323.5 used,   6500.9 buff/cache
MiB Swap:   3908.0 total,   2935.3 free,    972.7 used.   5898.7 avail Mem
 
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
3148828 oracle    20   0  769616 183112 177772 R  28.2   2.3   0:09.52 oracle_3148828_
3148827 oracle    20   0  769680 183868 178428 R  27.9   2.3   0:09.31 oracle_3148827_
3148820 oracle    20   0  771728 184600 178480 S  27.2   2.3   0:08.96 oracle_3148820_
3148818 oracle    20   0  769600 187388 181620 R  26.6   2.3   0:09.42 oracle_3148818_
3148812 oracle    20   0  769680 182748 177500 S  26.2   2.2   0:08.78 oracle_3148812_
3148823 oracle    20   0  769600 183108 177964 S  25.9   2.3   0:08.93 oracle_3148823_
3148813 oracle    20   0  768576 180240 175508 R  25.6   2.2   0:08.85 oracle_3148813_
3148824 oracle    20   0  771748 189200 183104 S  21.9   2.3   0:07.84 oracle_3148824_
3148819 oracle    20   0  769676 186904 181444 S  20.6   2.3   0:07.94 oracle_3148819_
3148832 oracle    20   0  768576 183980 179172 S  20.3   2.3   0:07.80 oracle_3148832_
3148766 oracle    20   0  772740 213968 206100 S  14.6   2.6   0:02.96 oracle_3148766_
3148395 oracle    20   0  764816  68476  65640 R   4.3   0.8   0:01.54 ora_lg00_oracle
    263 root       0 -20       0      0      0 I   4.0   0.0   3:50.78 kworker/0:1H-kblockd
   2192 root      20   0 2300624 303048  11780 S   3.7   3.7  91:13.26 java
     63 root       0 -20       0      0      0 I   3.0   0.0   1:53.66 kworker/2:1H-kblockd
3148517 oracle    20   0  784512 106604  99628 S   3.0   1.3   0:00.34 ora_cjq0_oracle
    261 root       0 -20       0      0      0 I   2.7   0.0   5:00.05 kworker/1:1H-kblockd

 

 

참고 : system 테이블스페이스 공간이 작을경우 아래 에러 발생함

1
2
3
4
*
ERROR at line 1:
ORA-01653: unable to extend table SYS.SETTINGS$ by 128 in tablespace SYSTEM
ORA-06512: at line 8

 

 

수행시 로그스위치 수회 발생함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ tail -300f /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/alert_oracle19.log
2025-03-09T13:13:23.467780+09:00
Thread 1 advanced to log sequence 2 (LGWR switch)
  Current log# 2 seq# 2 mem# 0: /oradata1/ORACLE19/redo02.log
2025-03-09T13:13:25.840864+09:00
ARC1 (PID:2437441): Archived Log entry 1 added for T-1.S-1 ID 0xc8f1bd0c LAD:1
2025-03-09T13:15:14.472101+09:00
Thread 1 advanced to log sequence 3 (LGWR switch)
  Current log# 3 seq# 3 mem# 0: /oradata1/ORACLE19/redo03.log
2025-03-09T13:15:15.852854+09:00
ARC2 (PID:2437443): Archived Log entry 2 added for T-1.S-2 ID 0xc8f1bd0c LAD:1
2025-03-09T13:16:59.471746+09:00
Thread 1 advanced to log sequence 4 (LGWR switch)
  Current log# 1 seq# 4 mem# 0: /oradata1/ORACLE19/redo01.log
2025-03-09T13:17:00.841991+09:00
ARC3 (PID:2437445): Archived Log entry 3 added for T-1.S-3 ID 0xc8f1bd0c LAD:1
2025-03-09T13:18:44.474996+09:00
Thread 1 advanced to log sequence 5 (LGWR switch)
  Current log# 2 seq# 5 mem# 0: /oradata1/ORACLE19/redo02.log
2025-03-09T13:18:45.923809+09:00
ARC0 (PID:2437415): Archived Log entry 4 added for T-1.S-4 ID 0xc8f1bd0c LAD:1
2025-03-09T13:20:29.470045+09:00
Thread 1 advanced to log sequence 6 (LGWR switch)
  Current log# 3 seq# 6 mem# 0: /oradata1/ORACLE19/redo03.log
2025-03-09T13:20:30.852176+09:00
ARC1 (PID:2437441): Archived Log entry 5 added for T-1.S-5 ID 0xc8f1bd0c LAD:1
2025-03-09T13:22:17.470581+09:00
Thread 1 advanced to log sequence 7 (LGWR switch)
  Current log# 1 seq# 7 mem# 0: /oradata1/ORACLE19/redo01.log
2025-03-09T13:22:18.799124+09:00
ARC2 (PID:2437443): Archived Log entry 6 added for T-1.S-6 ID 0xc8f1bd0c LAD:1

참고로 현재 redo 크기는 1gb임

 

 

생성한 오브젝트 확인

1
2
3
4
5
6
7
8
9
10
11
12
SQL>
select 'TEST_PROC', count(*) from dba_objects where object_name like 'TEST_PROC%'
union all
select 'TEST_FUNC', count(*) from dba_objects where object_name like 'TEST_FUNC%'
union all
select 'TEST_VIEW', count(*) from dba_objects where object_name like 'TEST_VIEW%';
 
'TEST_PRO   COUNT(*)
--------- ----------
TEST_PROC     400000
TEST_FUNC     300000
TEST_VIEW     300000

모두 정상적으로 생성됨

 

 

현재 오브젝트 갯수 확인

1
2
3
4
5
6
7
8
9
SQL> 
set timing on
select count(*) from dba_objects;
 
  COUNT(*)
----------
   1072376
 
Elapsed: 00:00:00.37

100만개가 증가함

 

 

현재 용량이 가장큰 오브젝트 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SQL>
set lines 200 pages 1000
col tablespace_name for a20
col segment_name for a40
col segment_type for a20
select * from 
 (select tablespace_name, segment_name, segment_type, bytes/1024/1024 mb 
  from dba_segments 
  where tablespace_name in ('SYSTEM', 'SYSAUX') 
  order by 4 desc)
where rownum <= 10;
 
TABLESPACE_NAME      SEGMENT_NAME                             SEGMENT_TYPE                 MB
-------------------- ---------------------------------------- -------------------- ----------
SYSTEM               IDL_UB1$                                 TABLE                       720
SYSTEM               IDL_UB2$                                 TABLE                       320
SYSTEM               C_OBJ#                                   CLUSTER                     256
SYSTEM               SETTINGS$                                TABLE                       232
SYSTEM               IDL_SB4$                                 TABLE                       176
SYSTEM               I_SETTINGS1                              INDEX                       176
SYSTEM               OBJ$                                     TABLE                       136
SYSTEM               I_IDL_UB11                               INDEX                       104
SYSTEM               SOURCE$                                  TABLE                        96
SYSTEM               I_IDL_SB41                               INDEX                        96
 
10 rows selected.

IDL_UB1$이 392mb에서 720mb로, IDL_UB2$이 30mb에서 320mb로, SOURCE$이 38mb에서 96mb로 증가함
그리고 C_OBJ#라는 오브젝트도 256mb로 3번째에 존재함, 기존에는 16mb이하였는지 top 10에 없었음

 

 

현재 shared pool 메모리 사용량 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SQL> 
select * from (
select name, bytes/1024/1024 as size_mb 
from v$sgastat 
where pool = 'shared pool' 
order by 2 desc)
where rownum <= 10;
 
NAME                          SIZE_MB
-------------------------- ----------
free memory                40.0060425
ksunfy_meta 1              12.8199463
kglsim object batch        8.86241913
row cache mutex            8.60121918
ASH buffers                         8
KGLH0                      7.92325592
kglsim heap                7.85595703
SO private sga             7.28937531
private strands            7.14355469
row cache hash             5.73414612
 
10 rows selected.

SQLA(SQL Area)가 기존 19mb에서 5mb로 이하 줄어듬(top 10 목록에 안나옴)

 

 

사용량 sum 해서 확인

1
2
3
4
5
SQL> select sum(bytes/1024/1024) as size_mb from v$sgastat where pool = 'shared pool';
 
   SIZE_MB
----------
       256

256으로 증가됨

 

 

sga 영역별 크기 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SQL>
select component, current_size/1024/1024 as size_mb
from v$sga_dynamic_components;
 
COMPONENT                                                           SIZE_MB
---------------------------------------------------------------- ----------
shared pool                                                             256
large pool                                                                4
java pool                                                                 0
streams pool                                                              0
unified pga pool                                                          0
memoptimize buffer cache                                                  0
DEFAULT buffer cache                                                     20
KEEP buffer cache                                                         0
RECYCLE buffer cache                                                      0
DEFAULT 2K buffer cache                                                   0
DEFAULT 4K buffer cache                                                   0
DEFAULT 8K buffer cache                                                   0
DEFAULT 16K buffer cache                                                  0
DEFAULT 32K buffer cache                                                  0
Shared IO Pool                                                            4
Data Transfer Cache                                                       0
In-Memory Area                                                            0
In Memory RW Extension Area                                               0
In Memory RO Extension Area                                               0
ASM Buffer Cache                                                          0
 
20 rows selected.

shared pool 크기가 기존 240mb에서 256mb로 증가됨
DEFAULT buffer cache 공간이 36mb에서 20mb로 줄어듬

 

 

파싱 카운트 확인

1
2
3
4
5
6
7
8
9
10
11
SQL>
set lines 200 pages 1000
col name for a30
select name, value
from v$sysstat
where name in ('parse count (total)', 'parse count (hard)');
 
NAME                                VALUE
------------------------------ ----------
parse count (total)              21632803
parse count (hard)                2033329

 

 

v$sql에 sql이 몇개 저장되는지 확인을 위해 쿼리 수행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL>
set timing on
DECLARE
    v_sql VARCHAR2(200);
BEGIN
    FOR i IN 1..10000 LOOP
        v_sql := 'SELECT /* test2025_02 */ COUNT(*) FROM DBA_OBJECTS WHERE OBJECT_ID = ' || TRUNC(DBMS_RANDOM.VALUE(1, 100000));
        EXECUTE IMMEDIATE v_sql;
    END LOOP;
END;
/
 
PL/SQL procedure successfully completed.
Elapsed: 00:01:20.64

 

 

위 sql 수행 직후 파싱 카운트 확인

1
2
3
4
5
6
7
8
9
10
11
SQL>
set lines 200 pages 1000
col name for a30
select name, value
from v$sysstat
where name in ('parse count (total)', 'parse count (hard)');
 
NAME                                VALUE
------------------------------ ----------
parse count (total)              21663580
parse count (hard)                2044249

 

 

파싱 카운트 계산

1
2
3
4
5
SQL> select 21663580-21632803 "total", 2044249-2033329 "hard" from dual;
 
     total       hard
---------- ----------
     30777      10920

1만회 pl/sql 수행시 각각 total : 30777, hard : 10920 증가함
100만개 오브젝트 추가전에는 각각 total : 30746, hard : 10369 증가했었음
하드파싱이 600개정도 더 증가한듯함(dbms_random을 사용한거라 랜덤값이 어떻게 사용됬는지에 따라서도 다를수 있긴함)

 

 

v$sql의 총 sql 갯수 및 테스트 sql 갯수 확인

1
2
3
4
5
6
7
8
9
SQL> 
select 'all sql', count(*) from v$sql
union all
select 'test sql', count(*) from v$sql where sql_text like '%SELECT /* test2025_02 */%';
 
'ALLSQL'   COUNT(*)
-------- ----------
all sql         332
test sql         38

v$sql에 총 332개 sql이 존재하고 test sql은 38개 존재함
shared pool에 library cache 사용량이 늘어나 sqla(sql area) 공간이 부족해져서 v$sql에 기존보다 sql이 적게 저장됨(표시됨)
빠르게 aging out 된다는 말이고, 이 말은 하드파싱이 많이 발생할수 있다는 말임

 

 

테스트 후 오브젝트 정리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SQL>
BEGIN
    FOR i IN 1..400000 LOOP
        EXECUTE IMMEDIATE 'DROP PROCEDURE test_proc_' || i;
    END LOOP;
END;
/
 
BEGIN
    FOR i IN 1..300000 LOOP
        EXECUTE IMMEDIATE 'DROP FUNCTION test_func_' || i;
        EXECUTE IMMEDIATE 'DROP VIEW test_view_' || i;
    END LOOP;
END;
/

 

 

결론 :
shared pool을 작게 설정한 상태에서 대량의 오브젝트를 생성하면 library cache 부하 증가와 shared pool 메모리 부족으로 성능 저하가 발생할 가능성이 높음
본문에는 작성하지 않았지만 30만개 오브젝트 생성 후 특정 작업들을 할때 ORA-04031이 발생하였음

1
2
3
ERROR at line 1:
ORA-04031: unable to allocate 152 bytes of shared memory ("shared pool","SELECT /* test2025_01 */ COU...","KGLH0^683cc1e3","wds: qksmmGetWorkArea")
ORA-06512: at line 6

 

 

그리고 shared pool 이 부족한 경우 sql을 저장할 sql area의 공간이 없어져서 자주 aging out이 일어나고 이로인해 하드파싱이 증가할 수 있음
또한 가용가능한 sga 메모리중 일부를 shared pool 크기로 재할당하여 크기를 증가시킴
본문에서도 기존 shared pool 크기를 240mb로 할당하였지만 기존 DEFAULT buffer cache에서 사용하던 36mb중 일부를 shared pool에 추가함

 

 

이렇게 오브젝트가 많은 경우 일부 시스템 뷰(딕셔너리)를 읽을때 쿼리가 느릴 수 있음
본문에서도 dba_objects뷰 전체 count시 기존에는 0.07초 소요되었지만 100만개 오브젝트 추가 이후에는 00.37초 소요됨

 

 

이 경우 fixed object 통계와 dictionary 통계를 재수집해주면 빨라질 수 있음(오라클 sr등 검토를 받은후 진행하는걸 권장함)

1
2
SQL> exec dbms_stats.gather_dictionary_stats;
SQL> exec dbms_stats.gather_fixed_objects_stats;

*전체 오브젝트보다 특정 느린 오브젝트만 통계를 수집해주는것도 방법임
참고 : 
https://blog.naver.com/seuis398/70178552040

 

 

참조 : 

3013269.1
https://forums.oracle.com/ords/r/apexds/community/q?question=sum-shareable-mem-vs-sqla-in-v-sgastat-0785
https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-LIBRARY_CACHE_MEMORY.html
https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-LIBRARYCACHE.html
https://docs.oracle.com/en/database/oracle/oracle-database/19/tgdba/tuning-shared-pool-and-large-pool.html#GUID-B3D48D5B-D19D-4E0F-84F0-1276FA113581
https://docs.oracle.com/en/database/oracle/oracle-database/19/spmsu/regathering-fixed-objects-statistics.html
https://docs.oracle.com/en/database/oracle/oracle-database/19/spmsu/gathering-dictionary-statistics-after-upgrading.html
https://blog.naver.com/seuis398/70178552040