05 데이터베이스 Call 최소화 원리

Call 통계

아래는 sql trace report에서 Call 통계(Statistic)부분만을 발췌한 것이다. 이 레포트는 커서의 활동상태를 Parse, Execute, Fetch 세 단계로 나누어 각각에 대한 수행통계를 보여준다.


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.01       0.00         80         59          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.01       0.00         80         59          0           1

Misses in library cache during parse: 1
Misses in library cache during execute: 1

  • Parse Call{}은 커서를 파싱하는 과정에 대한 통계로서, 실행계획을 생성하거나 찾는 과정에 관한 정보를 포함한다.
  • Execute Call{}은 말 그대로 커서를 실행하는 단계에 대한 통계를 보여준다.
  • Fetch Call{}은 select문에서 실제 레코드를 읽어 사용자가 요구한 결과집합을 반환하는 과정에 대한 통계를 보여준다.
insert, update, delete, merge 등 DML문은

Execute Call 시점에 모든 처리과정을 서버내에서 완료하고 처리결과만 리턴하므로 Fetch Call이 전혀 발생하지 않는다.


delete
  from big_table
 where rownum = 1

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0         61          0           0
Execute      1      0.00       0.00          0          4          3           1
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.00          0         65          3           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 41  

Rows     Row Source Operation
-------  ---------------------------------------------------
      1  DELETE  BIG_TABLE (cr=4 pr=0 pw=0 time=114 us)
      1   COUNT STOPKEY (cr=4 pr=0 pw=0 time=34 us)
      1    TABLE ACCESS FULL BIG_TABLE (cr=4 pr=0 pw=0 time=30 us)

insert... select 문

클라이언트로부터 명시적인 Fatch Call을 받지 않으며 서버 내에서 묵시적으로 Fatch가 이루어진다.
의문.: CATS도 마찬가지 일까? 나는 CATS로 테스트함. 맞는거는 같은데... 정확히 답좀 해주세요..


create table big_table as
select *
  from all_tables
 where rownum <= 10000

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.18       0.22          0          0          0           0
Execute      1      0.43       0.63         24       7659        401        2759
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.61       0.86         24       7659        401        2759

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS

Select문

Excetue Call 단계에서는 커서만 오픈하고, 실제 데이터를 처리하는 과정은 모두 Fatch 단계에서 일어난다.
예를들어, sort group by는 Execute 단계에서 처리할 것으로 예상되지만 실제로는 Fetch 시점에 처리가 일어난다. 실제 데이터를 액세스하면서 일을 시작하는 시점은 첫 번째 Fetch Call 인 것을 짐작할 수 있다.


select owner, count(*)
  from big_table
 group by owner

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          1          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.01       0.00          0         88          0          18
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.01       0.00          0         89          0          18

for update 구문

Execute Call 단계에서 모든 레코드를 읽어 Lock을 설정한다.


-- 내가 돌린쿼리
select *
  from big_table for update

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.02       0.00          0          1          0           0
Execute      1      0.03       0.03          4         88       2811           0
Fetch       28      0.03       0.02          0        115          0        2759
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       30      0.08       0.06          4        204       2811        2759

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 41  

Rows     Row Source Operation
-------  ---------------------------------------------------
   2759  FOR UPDATE  (cr=203 pr=4 pw=0 time=42812 us)
   5518   TABLE ACCESS FULL BIG_TABLE (cr=203 pr=4 pw=0 time=5646 us)


-- 책의 결과
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.02       0.00          0          1          0           0
Execute      1      0.03       0.03          4         88      10178           0
Fetch       11      0.03       0.02          0        115          0         101
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       13      0.08       0.06          4        204      10178         101


-- 내가 100건만 돌린 결과 
select *
  from big_table
 where rownum <= 100
 for update

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.02          0        120          0           0
Execute      1      0.00       0.00          0          7        104           0
Fetch        2      0.01       0.00          0          7          0         100
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.01       0.03          0        134        104         100

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 41  

Rows     Row Source Operation
-------  ---------------------------------------------------
    100  FOR UPDATE  (cr=14 pr=0 pw=0 time=1688 us)
    200   COUNT STOPKEY (cr=14 pr=0 pw=0 time=490 us)
    200    TABLE ACCESS FULL BIG_TABLE (cr=14 pr=0 pw=0 time=285 us)

책에서는 10,000건의 레코드가 있는 테이블을 for update 구문을 사용하여 실행시켰을때, Fetch단계에서는 101개의 레코드만 Fetch하고 멈추었지만, Execute 단계에서 이미 Current모드로 읽어 10,000개 레코드 전체에 대해 Lock을 설정했다고 되어있다.

의문: Execute 단계에서 이미 Current모드로 읽어 10,000개 레코드 전체에 대해 Lock을 설정했다는 건 이해가 가는데... Fecth 101건만 읽은 이유는 무었일까? for update단계에서 무슨일이 일어난걸까... 내가 테스트한 거에서는 저런 내용이 안나옴.... 나혼자만 실행해서 그런거일거라 생각은 듬...

문서에 대하여

  • 최초작성자 : 한남주
  • 최초작성일 : 2010년 4월 11일
  • 이 문서는 오라클클럽 대용량 데이터베이스 스터디 모임에서 작성하였습니다.
  • {*}이 문서의 내용은 (주)비투엔컬설팅에서 출간한 '오라클 성능 고도화 원리와 해법I'를 참고하였습니다.*