Data Base/SQL 튜닝

Serial direct read

잇꼬 2024. 2. 17. 21:29
728x90
반응형
SMALL

#) 한번에 읽을 수 있는 블록의 개수 확인

show parameter db_file_multiblock_read_count

- direct path read: 병렬처리할 경우 발생하는 대기 이벤트, 22 번 올렸다.

■ Serial direct read

1. full scan 및 multi block i/o : 데이터베이스에서 전체 테이블 또는 인덱스를 스캔할 때, 여러 블록을 한 번에 읽는 Multi Block I/O가 발생.

2. Data buffer cache 부담 : 데이터 버퍼 캐시에 부하 가능성

3. Latch: cache buffers lru chain 이벤트 : 데이터 파일의 블록을 메모리로 읽어올 때 `cache buffers lru chain` 이벤트에 따른 Latch를 사용

4. LRU 리스트의 COLD 영역에서 블록 읽기 : Latch를 획득하고 LRU 리스트의 끝에서 블록을 읽어온다. 

- 여기서 COLD 영역은 오랫동안 사용되지 않은 블록이 위치한 부분을 나타낸다.

5. Age Out 문제 : 읽어들인 블록이 메모리에서 밀려나게 되면(Age Out), 해당 블록이 다시 필요한 경우 물리적 I/O가 발생 할 수 있다.

6. Direct Read 기능: 이러한 문제를 해결하기 위해, "serial direct read" 방식을 제안한다.

- 이는 데이터를 데이터 버퍼 캐시에 올리지 않고, 대신 서버 프로세스의 PGA(Private Global Area) 영역에 있는 커서(cursor)에서 바로 데이터 파일에서 읽어오는 방식

7. Parallel 처리와의 연관: 원래는 병렬 처리 시에 발생하는 기능이었지만, Oracle Database 11g부터는 병렬 처리 힌트를 사용하지 않아도 "serial direct read" 방식이 구현되었다.

 

※ serial direct read의 총 정리.

풀 스캔 시 발생하는 블록 읽기 작업에서 데이터 버퍼 캐시 부하와 관련된 문제를 해결하기 위해 도입된 기능으로, 데이터를 직접 읽어와서 메모리에 저장하는 것이 아니라 PGA의 커서를 통해 바로 읽어오는 방식.

 

SELECT a.ksppinm Parameter, b.ksppstvl session_value, c.ksppstvl lnstance_value
FROM x$ksppi a, x$ksppcv b, x$ksppsv c
WHERE a.indx = b.indx
AND a.indx = c.indx
AND a.ksppinm in ('_small_table_threshold', '_serial_direct_read');

#1) _small_table_threshold : 기준치

<hr sess>

exec dbms_application_info.set_client_info('sess_1')
select count(*) from ind_random where owner = 'SYS';


<sys sess>
#) sess sid 확인

select client_info, sid from v$session where client_info = 'sess_1';

 

 

#) 모니터링 쿼리문

- 대기 이벤트 확인  

select sid, event, wait_class, wait_time, seconds_in_wait, state 
from v$session_wait 
where sid = 28;

select sid, event, total_waits, time_waited from v$session_event where sid = 28;


alter system flush buffer_cache;
alter system flush buffer_cache;

#) hr 계정 재접속 

exec dbms_application_info.set_client_info('sess_1')
select count(*) from ind_random where owner = 'SYS';

<sys sess>

select client_info, sid from v$session where client_info = 'sess_1';

#) 대기 이벤트 확인

select sid, event, total_waits, time_waited from v$session_event where sid = 28;
       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
        28 Disk file operations I/O                                                   3           0
        28 db file sequential read                                                   11           6
        28 direct path read                                                          22           0
        28 SQL*Net message to client                                                 15           0
        28 SQL*Net message from client                                               14        3332


<new sess_hr>

exec dbms_application_info.set_client_info('sess_2')


# direct path read 방식을 안하겠다는 이벤트

alter session set events '10949 trace name context forever, level 1';
select count(*) from ind_random where owner = 'SYS';


<sys sess>

select client_info, sid from v$session where client_info = 'sess_2';
CLIENT_INFO                           SID
------------------------------ ----------
sess_2                                151


#) db file scattered read

- (해석)멀티블록 i/o 발생 -> data buffer cache 건드리고 있다.

select sid, event, total_waits, time_waited from v$session_event where sid = 151;
       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
       151 Disk file operations I/O                                                   1           0
       151 log file sync                                                              1           2
       151 db file scattered read                                                    23           0
       151 SQL*Net message to client                                                 16           0
       151 SQL*Net message from client                                               15        1937

#) 이벤트 취소

alter session set events '10949 trace name context off';

alter system flush buffer_cache;
alter system flush buffer_cache;

 

<시나리오 _trace 및 대기 이벤트 생성>
<hr sess>
#) trace 하기

alter session set events '10949 trace name context forever, level 1';
alter session set tracefile_identifier = 'hr';
alter session set events '10046 trace name context forever, level 8';
select count(*) from hr.ind_random where owner = 'SYS';
alter session set events '10046 trace name context off';
alter session set events '10949 trace name context off';


[oracle1@oracle ~]$ cd $ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace
[oracle1@oracle trace]$ ls *hr.trc
ora11g_ora_2305_hr.trc
[oracle1@oracle trace]$ tkprof ora11g_ora_2305_hr.trc ex03.txt sys=no
[oracle1@oracle trace]$ vi ex03.txt
...

********************************************************************************

SQL ID: 49g6ju0tm1s80 Plan Hash: 3056395443

select count(*)
from
 hr.ind_random where owner = 'SYS'


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.01          0          0          0           0
Fetch        2      0.00       0.00        986        990          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.02        986        990          0           1

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 84
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=990 pr=986 pw=0 time=8412 us)
     29855      29855      29855   TABLE ACCESS FULL IND_RANDOM (cr=990 pr=986 pw=0 time=3592 us cost=276 size=377366 card=22198)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       2        0.00          0.00
  Disk file operations I/O                        1        0.00          0.00
  db file sequential read                         1        0.00          0.00
  db file scattered read                         23        0.00          0.00
  SQL*Net message from client                     2        4.10          4.10
********************************************************************************

 

<sys sess>

show parameter db_file_multiblock_read_count
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count        integer     126



select extent_id, block_id, bytes, blocks
from dba_extents
where owner = 'HR'
and segment_name = 'IND_RANDOM';
 EXTENT_ID   BLOCK_ID      BYTES     BLOCKS
---------- ---------- ---------- ----------
         0      19240      65536          8
         1      19248      65536          8
         2      19256      65536          8
         3      19264      65536          8
         4      19272      65536          8
         5      19280      65536          8
         6      19288      65536          8
         7      19296      65536          8
         8      19304      65536          8
         9      19312      65536          8
        10      19320      65536          8
        11      19328      65536          8
        12      19336      65536          8
        13      19344      65536          8
        14      19352      65536          8
        15      19360      65536          8
        16      19456    1048576        128  /* => 2번씩의 i/o 발생 */
        17      19584    1048576        128
        18      19712    1048576        128
        19      19840    1048576        128
        20      19968    1048576        128
        21      20096    1048576        128
        22      20224    1048576        128

 


<시나리오 재진행>

alter system flush buffer_cache;
alter system flush buffer_cache;


<hr sess 재접속>

alter session set db_file_multiblock_read_count = 128;
alter session set events '10949 trace name context forever, level 1';
alter session set tracefile_identifier = 'ran';
alter session set events '10046 trace name context forever, level 8';
select count(*) from hr.ind_random where owner = 'SYS';
alter session set events '10046 trace name context off';
alter session set events '10949 trace name context off';



[oracle1@oracle ~]$ cd $ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace
[oracle1@oracle trace]$ ls *ran.trc
ora11g_ora_3088_ran.trc
[oracle1@oracle trace]$ tkprof ora11g_ora_3088_ran.trc ex01.txt
[oracle1@oracle trace]$ vi ex01.txt
...

index full scan => 싱글 블록



<시나리오 재진행_trace>
<sys sess>

alter system flush buffer_cache;
alter system flush buffer_cache;


<hr sess 재접속>
#) index 생성 

create index hr.ind_random_ix on hr.ind_random(owner);

 

alter session set tracefile_identifier = 'hr';
alter session set events '10046 trace name context forever, level 8';
select count(*) from hr.ind_random where owner = 'SYS';
alter session set events '10046 trace name context off';


#) trace 확인 
[oracle1@oracle ~]$ cd $ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace
[oracle1@oracle trace]$ ls *hr.trc
ora11g_ora_3619_hr.trc
[oracle1@oracle trace]$ tkprof ora11g_ora_3964_hr.trc ex02.txt
[oracle1@oracle trace]$ vi ex02.txt
...


 

<시나리오 재진행_trace>
<sys sess>

alter system flush buffer_cache;
alter system flush buffer_cache;


<hr sess 재접속>

alter session set tracefile_identifier = 'hr';
alter session set events '10046 trace name context forever, level 8';
select * from hr.ind_random where owner = 'SYS';
alter session set events '10046 trace name context off';



[oracle1@oracle ~]$ cd $ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace
[oracle1@oracle trace]$ ls *hr.trc
ora11g_ora_4043_hr.trc
[oracle1@oracle trace]$ tkprof ora11g_ora_4043_hr.trc ex03.txt
[oracle1@oracle trace]$ vi ex03.txt
...

 



<시나리오 재진행_trace>
<sys sess>

alter system flush buffer_cache;
alter system flush buffer_cache;


<hr sess 재접속>

alter session set tracefile_identifier = 'hr';
alter session set events '10046 trace name context forever, level 8';
select /*+ index(i ind_random_ix)*/ * from hr.ind_random i where owner = 'SYS';
alter session set events '10046 trace name context off';


<OS 에서 확인>
[oracle1@oracle ~]$ cd $ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace
[oracle1@oracle trace]$ ls *hr.trc
ora11g_ora_4220_hr.trc
[oracle1@oracle trace]$ tkprof ora11g_ora_4220_hr.trc ex04.txt
[oracle1@oracle trace]$ vi ex04.txt

...

 



<시나리오 재진행_trace>
<sys sess>

alter system flush buffer_cache;
alter system flush buffer_cache;


<hr sess 재접속>

alter session set tracefile_identifier = 'hr';
alter session set events '10046 trace name context forever, level 8';
select /*+ index(i ind_random_ix)*/ * from hr.ind_random i where owner = 'SYS' and object_name = 'ALL_OBJECTS';
alter session set events '10046 trace name context off';

 


[oracle1@oracle ~]$ cd $ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace
[oracle1@oracle trace]$ ls *hr.trc
 ora11g_ora_5653_hr.trc
[oracle1@oracle trace]$ tkprof ora11g_ora_5653_hr.trc ex05.txt
[oracle1@oracle trace]$ vi ex05.txt
...

=> 쓸데없는 i/o 발생 -> random i/o 발생 | buffer pinning 발생했으나 너무 많은 i/o 발생 => 조합 인덱스 실행


#) 위에 대한 해결방안 -> 조합인덱스
<시나리오 재진행_trace>
<hr sess>

drop index ind_random_ix;
create index hr.ind_random_ix on hr.ind_random(owner, object_name);


<sys sess>

alter system flush buffer_cache;
alter system flush buffer_cache;


<hr sess 재접속>

alter session set tracefile_identifier = 'hr';
alter session set events '10046 trace name context forever, level 8';
select /*+ index(i ind_random_ix)*/ * from hr.ind_random i where owner = 'SYS' and object_name = 'ALL_OBJECTS';
alter session set events '10046 trace name context off';


[oracle1@oracle ~]$ cd $ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace
[oracle1@oracle trace]$ ls *hr.trc
 ora11g_ora_5653_hr.trc
[oracle1@oracle trace]$ tkprof ora11g_ora_5896_hr.trc ex06.txt
[oracle1@oracle trace]$ vi ex06.txt
...


※ 설명)
1. db file sequential read

1) 발생 시점: index range scan, index full scan

2) I/O 방식: Single Block I/O로, 한 번의 I/O 호출에 하나의 데이터 블록만 읽어온다.

3) 발생 시점 기준: 주로 인덱스를 사용하여 원하는 행을 찾을 때 발생한다. 인덱스가 있는 열을 검색하는 쿼리에서 발생할 가능성이 높다.

4) 주로 인덱스를 통해 테이블을 액세스할 때 발생하며, 인덱스의 범위를 스캔할 때 사용된다.


2. db file scattered read
1) 발생시점: full table scan, index fast full scan

2) I/O방식: Multi-Block I/O로, 한 번의 I/O 호출에 인접한 블록들을 메모리에 읽어온다.

3) 발생 시점 기준: `db_file_multiblock_read_count의 값에 의해 결정되며, 해당 값은 데이터베이스 설정에 의해 결정된다.4) 대량의 데이터를 검색할 때 사용되며, 한 번에 여러 블록을 읽어올 수 있다. `db_file_multiblock_read_count`를 조절하여 한 번에 읽을 수 있는 블록 수를 설정할 수 있다. 적절한 값을 유지하는 것이 성능에 도움이 된다.

728x90
반응형
LIST