메뉴 건너뛰기

bysql.net

5. 바인드 변수의 중요성

2010.06.28 08:04

실천하자 조회 수:11765

5. 바인드 변수의 중요성


  • 인덱스 생성 -> 통계정보 수집 -> 실행계획 (정상적 인덱스 사용 확인) - (우분투9, 오라클 10gR2)
SQL> create table t as select * from all_objects;

Table created.

SQL> update t set object_id = rownum;

49832 rows updated.

SQL> create unique index t_idx on t(object_id);

Index created.

SQL> analyze table t compute statistics;

Table analyzed.

SQL> set autotrace traceonly explain
SQL> select object_name from t where object_id = 1000;

Execution Plan
----------------------------------------------------------
Plan hash value: 2929955852

-------------------------------------------------------------------------------------
| Id  | Operation            | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |        |      1 |     28 |      2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |      1 |     28 |      2   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN        | T_IDX |      1 |        |      1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=1000)

SQL> set autotrace off
SQL> alter system flush shared_pool;

System altered.



  • 바인드 변수 사용 - (우분투9, 오라클 10gR2)
SQL> SET TIMING ON
SQL> DECLARE
  2    TYPE rc IS REF CURSOR;
  3    l_rc rc;
  4    l_object_name t.object_name%TYPE;
  5  BEGIN
  6    FOR i IN 1 .. 20000
  7    LOOP
  8     OPEN l_rc FOR
  9        'SELECT /* test1 */ object_name
 10           FROM t
 11         WHERE  object_id = :x' USING i;
 12     FETCH l_rc INTO l_object_name;
 13     CLOSE l_rc;
 14    END LOOP;
 15  END;
 16  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:02.82

SQL> SELECT sql_text, loads, parse_calls, executions, fetches
  2  FROM   v$sql
  3  WHERE  sql_text LIKE '%test1%'
  4  AND    sql_text NOT LIKE '%v$sql%'
  5  AND    sql_text NOT LIKE '%DECLARE%';

SQL_TEXT                                                     LOADS PARSE_CALLS EXECUTIONS    FETCHES
---------------------------------------------------------- ------- ----------- ---------- ----------
SELECT /* test1 */ object_name FROM t WHERE object_id = :x     1     20000        20000      20000


Elapsed: 00:00:00.13


20,000번 SQL 수행 시간 : 2.82초(교재 : 1.23 초)

v$sql 뷰를 이용하여 커서의 수행통계 확인


SQL 트레이스를 이용한 리포트 결과 (교재 결과 인용 - p.274)

call     count       cpu    elapsed       disk      query    current        rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 20000 0.16 0.17 0 0 0 0
Execute 20000 0.22 0.42 0 0 0 0
Fetch 20000 0.45 0.47 0 60000 0 20000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 60000 1.23 1.07 0 60000 0 20000

Misses in library cache during parse: 1



  • 바인드 변수 사용 X, 조건절에 Literal 상수값 동적 사용 - (우분투9, 오라클 10gR2)

SQL> DECLARE
  2    TYPE rc IS REF CURSOR;
  3    l_rc rc;
  4    l_object_name t.object_name%TYPE;
  5  BEGIN
  6    FOR i IN 1 .. 20000
  7    LOOP
  8      OPEN l_rc FOR
  9       'SELECT /* test2 */ object_name
 10         FROM t
 11        WHERE object_id = ' || i;
 12     FETCH l_rc INTO l_object_name;
 13     CLOSE l_rc;
 14    END LOOP;
 15  END;
 16  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:34.37

SQL> SELECT SUBSTR(sql_text, 56, 25) sql_text, loads, parse_calls, executions, fetches
  2  FROM   v$sql
  3  WHERE  sql_text LIKE '%test2%'
  4  AND    sql_text NOT LIKE '%v$sql%'
  5  AND    sql_text NOT LIKE '%DECLARE%';

SQL_TEXT               LOADS PARSE_CALLS EXECUTIONS    FETCHES
------------------------- ---------- ----------- ---------- ----------
E object_id = 19892           1           1      1         1
E object_id = 19768           1           1      1         1

E object_id = 19821           1           1      1         1
E object_id = 19571           1           1      1         1

451 rows selected.

Elapsed: 00:00:00.21



20,000번 SQL 수행 시간 : 34.37초 (교재 9.03 초 7.3배)

이전 결과와 12.2배 차이


v$sql 뷰를 이용하여 커서의 수행통계 확인

수행된 SQL 각각에 대해 커서가 따로 생성, 매번 하드파싱 일으킴 (경과 시간 차이의 원인)

교재 결과를 기준으로 결과 건수가 2,319개인 것을 볼 때 SQL Area 중 17,681개는 이미 캐시에서 밀려나고 없음

(테스트 결과 기준 시 결과 건수가 451개로 SQL Area 중 19,549개는 캐시에서 밀려남)


※ 참고 Shared Pool Size

SQL> SELECT * from v$sga;

NAME                           VALUE
-------------------- ----------
Fixed Size                     1218992
Variable Size              100664912
Database Buffers         180355072
Redo Buffers                  2973696


☞ 옵티마이저 힌트도 없고, 로직 수정도 없이 프로그램 작성 패턴만 조금 변경했지만 성능 및 시스템 리소스 사용 측면에서 엄청난 차이 발생


동일한 작업의 SQL을 계속 호출 시 해당 프로시저가 하나 씩 생성(옵티마이저 & Row-Source Generator)

조건의 값이 들어간 데이터 분포가 편중되지 않을 시 프로시저의 내부 처리 루틴은 모두 같을 것이기에 조건의 값을 파라미터로 받아 하나의 프로시저로 처리하도록 하는 것이 효율적

☞ 파라미터 Driven 방식으로 SQL 작성 방법 제공

→ 변수 사용 (하나의 프로시저를 공유로 반복 및 재사용 효과)

→ 메모리 사용량과 파싱 소요시간 감소

→ 시스템 전반의 메모리와 CPU 사용률을 낮춰 데이터 베이스 성능과 확장성을 높이는데 기여

    동시 사용자 접속이 많을 때 영향력 ↑


※ 참고

    바인드 변수 사용 원칙에 따라 라이브러리 캐시 경합 발생으로 시스템 정상 가동이 어려울 수 있음

    ☞ cursor_sharing 파라미터 변경 (응급처방 용)

번호 제목 글쓴이 날짜 조회 수
67 Front Page file 운영자 2010.05.17 154865
66 1 장. 오라클 아키텍처 운영자 2010.05.20 17842
65 1. 기본 아키텍처 [1] file 휘휘 2010.05.23 19899
64 3. 버퍼 Lock [1] 휘휘 2010.05.24 15225
63 2. DB 버퍼 캐시 file 휘휘 2010.05.24 21916
62 4. Redo file 휘휘 2010.05.24 11314
61 9. Snapshot too old balto 2010.05.30 8100
60 10. 대기 이벤트 balto 2010.05.30 8010
59 7. Consistent vs. Current 모드 읽기 휘휘 2010.05.31 10537
58 8. 블록 클린아웃 휘휘 2010.05.31 12283
57 11. Shared Pool file 실천하자 2010.05.31 18511
56 5. Undo file 토시리 2010.05.31 18651
55 1. 트랜잭션 동시성 제어 실천하자 2010.05.31 8631
54 6. 문장수준 읽기 일관성 file 토시리 2010.06.01 10432
53 2장. 트랜잭션과 Lock 운영자 2010.06.01 6895
52 1. Explain Plan 실천하자 2010.06.06 14663
51 2. AutoTrace 실천하자 2010.06.06 8597
50 3장. 오라클 성능 관리 운영자 2010.06.06 6694
49 3. SQL 트레이스 file balto 2010.06.06 21175
48 4. DBMS_XPLAN 패키지 balto 2010.06.06 10461