DATA 전문가로 가는 길

[Oracle] 데이터베이스 Call 최소화 원리 본문

Data Architecture/Tunning

[Oracle] 데이터베이스 Call 최소화 원리

EstenPark 2015. 12. 2. 23:26

 

 

 

Parse Call을 제외하고 SQL  수행 중에 발생하는 Execute Call, Fetch Call을 줄이는 방법에 대해 설명하고, 데이터베이스 Call을 User Call과 Recursive Call로 나누어 각각을 최소화하는 원리와 방안에 대해서 설명 합니다.

 

Call 통계

select * from emp;

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.03          0          0          0           0
Execute      1      0.00       0.01          0          0          0           0
Fetch        2      0.00       0.00          0          8          0          14
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.01       0.04          0          8          0          14

Misses in library cache during parse: 1


Parse Call : 커서를 파싱하는 과정에 대한 통계로서, 실행계획을 생성하거나 찾는 과정에 관한 정보를 포함 합니다.

Execute Call : 커서를 실행하는 단계에 대한 통계를 보여줍니다.

Fetch Call : SELECT문에서 실제 레코드를 읽어 사용자가 요구한 결과집합을 반환하는 과정에 대한 통계를 보여줍니다. (INSERT, UPDATE, DELETE문에서는 결과에 대한 Fetch Call만 리턴 하게 됩니다.)

 

위와 같은 결과는 Parse Call은 1번 수행했고, ,Execute Call도 1번 수행 했습니다. 최종 결과를 반환할 때 Fetch는 총 2회(총 14건) 발생 하였습니다.

 

delete from emp2


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.01          0          1          0           0
Execute      1      0.00       0.00          0          3         17          14
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.01          0          4         17          14

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

DELETE문에서 Parse Call과 Excute Call은 1회씩 진행되고, Fetch Call은 처리결과만 리턴 하므로 아무것도 발생하지 않은 것을 볼 수 있습니다.

insert into emp2
select * from emp

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.02          0          8          5          14
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.03          0          8          5          14

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

SELECT문에 있는 테이블의 데이터를 INSERT문에 있는 테이블로 이관할 때 사용하는 쿼리 이며, 클아이언트로부터 명시적인 Fetch Call을 받지 않으며 서버 내에서 묵시적으로 Fetch가 이루어졌습니다.

select * from
emp for update


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.00          0          0          0           0
Execute      1      0.00       0.00          0          7         14           0
Fetch        2      0.00       0.00          0          8          0          14
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.01       0.00          0         15         14          14

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

FOR UPDATE 구분을 사용하면 Execute Call 단계에서 모든 레코드를 읽어 Lock을 설정하게 됩니다. 따라서 위와 같이 14개의 레코드를 갖는 테이블을 FOR UPDATE 구문을 사용해 쿼리한 결과인데, 사용자는 2번의 Fetch Call을 통해 14개 레코드 Fetch 했습니다. 데이터가 더 많이 있을 경우에는 Current 모드로 읽어 전체 레코드를 Lock을 설정하게 됩니다.

 

User Call Vs. Recursive Call

 

User Call : OCI를 통해 오라클 외부로부터 들어오는 Call을 말합니다.
Recursive Call : 오라클 내부에서 발생하는 Call을 의미합니다.

 

User Call

 

DBMS 외부로부터 요청되는 Call을 말하며, 동시 접속자 수가 많은 Peak 시간대에 시스템 확장성을 떨어뜨리는 가장 큰 요인 중 한 가지는 User Call입니다. User Call이 많이 발생하도록 개발된 프로그램은 결코 성능이 좋을 수 없고, 이는 개발자의 기술력에 의해서도 좌우되지만 많은 경우 애플리케이션 설계와 프레임워크 기술구조에 기인합니다. 이를테면, Array Processing을 제대로 지원하지 않는 프레임워크, 화면 페이지 처리에 대한 잘못 설계된 표준가이드, 사용자 정의 함수/프로시저에 대한 무조건적인 제약 등이 그것입니다. 그리고 프로시저 단위 모듈을 지나치게 잘게 쪼개서 SQL을 건건이 호출하도록 설계하는 것도 대표적입니다. DBMS 성능과 확장성(Scalability)을 높이려면 User Call을 최소화하려는 노력이 무엇보다 중요하며, 이를 위해 아래와 같은 기술요소를 적극적으로 활용해야만 합니다.

 

  + Loop 쿼리를 해소하고 집합적 사고를 통해 One SQL로 구현

  + Array Processing : Array 단위 Fetch, Bulk Insert/Update/Delete

  + 부분범위처리 원리 활용

  + 효과적인 화면 페이지 처리

  + 사용자 정의 함수/프로시저/트리거의 적절한 활용

 

Recursive Call

 

DBMS 내부에서 발생하는 Call을 말합니다. SQL 파싱과 최적화 과정에서 발생하는 데이터 딕셔너리 조회, 사용자 정의 함수/프로시저 내에서의 SQL 수행이 여기에 해당합니다. Recursive Call을 최소화하려면, 바인드 변수를 적극적으로 사용해 하드파싱 발생횟수를 줄여야 합니다. 그리고 사용자 정의 함수와 프로시저가 어떤 특징을 가지며 내부적으로 어떻게 수행되는지를 잘 이해하고 시의 적절하게 사용해야만 합니다. 무조건 사용하지 못하도록 제약하거나 무분별하게 사용하지 말아야 한다는 뜻입니다.

 

 

데이터베이스  Call이 성능에 미치는 영향

바로가기

 

Array Processing 활용

바로가기

 

Fetch Call 최소화

 

  + 부분범위처리 원리

      쿼리 결과집합을 전송할 때, 전체 데이터를 쉼 없이 연속적으로 처리하지 않고, 사용자로부터 Fetch Call 이 있을 때마다 일정량씩 나누어서 전송하는 방식을 의미합니다.
      SDU (Session Data Unit) Session 레이어 데이터 버퍼에 대한 규격으로서, 네트워크를 통해 전송하기 전에 Oracle Net 이 데이터를 담아 두려고 사용하는 버퍼입니다.
      TDU (Transport Data Unit) Transport 레이어 데이터 버퍼에 대한 규격으로, 물리적인 하부 레이어로 내려보내기 전에 데이터를 잘게 쪼개어 클라이언트에게 전송되는 도중에 유실이나 에러가 없도록 제어하는 역할을 합니다.

  + OLTP 환경에서 부분처리에 의한 성능개선 원리

  + ArraySize 조정에 의한 Fetch Call 감소 및 블록 I/O 감소 효과

      대량 데이터를 내려받을 때 ArraySize 를 크게 설정할수록 그만큼 Fetch Call 횟수가 줄어 네트워크 부하가 감소하고, 쿼리 성능이 향상됩니다.
      그뿐만 아니라 서버 프로세스가 읽어야 할 블록 개수까지 줄어드는 일거양득의 효과를 얻게 됩니다.

  + 프로그램 언어에서 Array 단위 Fetch 기능 활용

 

 

출처

http://wiki.gurubee.net/pages/viewpage.action?pageId=26279938

http://bysql.net/index.php?mid=w201002&entry=5%EC%9E%A5.+%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4+Call+%EC%B5%9C%EC%86%8C%ED%99%94+%EC%9B%90%EB%A6%AC

 

 

Comments