출처 : KACHISORI
본 자료는 일본 @IT(http://www.atmarkit.co.jp/fdb/index/index-db.html#tuneorasql) 에 株式会社アゲハ加藤 猛씨가 연재한 Oracle SQLチューニング講座를 번역 재구성한 것입니다.
전회까지 SQL 튜닝을 실시하기 위해 필요한 기초지식을 설명했습니다. 이번회에서는 튜닝 대상으로 해야 할 SQL를 어떠한 관점으로부터 어떻게 골라내는지 설명합니다.
■ 튜닝이 필요한 SQL 골라내기
통상 어플리케이션에서는 많은 SQL이 실행되어지고 있습니다. SQL 튜닝의 스텝은 실행되고 있는 많은 SQL중에서 튜닝의 목표에 맞추어 대상 SQL를 밝혀내는 것부터 시작됩니다.
일반적으로 표 1의 조건을 1개이상 만족하는 SQL은 튜닝에 의한 개선이 가능할지를 검토하는 대상이 됩니다. 우선은 이러한 SQL를 밝혀내 튜닝의 최종 목표를 고려하고 대상으로 할 SQL를 결정해야 합니다.
예를 들면 특정 어플리케이션의 처리 속도 개선이 목표의 경우에는 해당 어플리케이션중에서 처리에 시간이 걸리는 SQL에 주목합니다. 또 시스템 전체의 throughput 향상이나 시스템 부하(CPU, 디스크 I/O등)의 절감을 목표로 하는 경우에는 많은 자원을 사용하고 있는 SQL나 실행 회수가 많은 SQL에 주목합니다.
|
1실행 당 실행 시간이 긴 SQL |
|
디스크 읽기 블록수가 많은 SQL |
|
버퍼의 읽기수가 극단적으로 많은 SQL |
|
실행 회수가 극단적으로 많은 SQL |
|
표 1 튜닝 대상으로서 골라니야할 SQL |
■ 대상 SQL의 선별 방법
튜닝 대상으로 선정할 SQL를 선별하는 방법은 이하의 2개가 있습니다.
-
동적 퍼포먼스뷰에서 SQL를 추출하는 방법
-
어플리케이션의 SQL 트레이스를 취득하는 방법
어플리케이션이 특정 되어 있는 경우라면 각 SQL의 해석 시간, 실행 시간, 실행 계획등의 정보를 간단하게 얻을 수 있는 SQL 트레이스의 취득이 가장 유효합니다. 취득한 트레이스 파일을 포맷 해 SQL를 「처리 시간」 「독해 블록수」 「실행 회수」등으로 소팅해 튜닝 대상의 SQL를 간단하게 좁힐 수 있습니다.
다만, SQL 트레이스는 비교적 부하가 높고 어플리케이션의 처리 속도에 영향을 줄수 있습니다. SQL 트레이스의 오버헤드가 부담되는 경우나 어플리케이션이 특정 되어 있지 않은 경우에는 동적 성능뷰(V$ 테이블)를 사용하는 방법을 검토합니다. 동적 성능뷰에도 각 SQL이 인스턴스 전체에서 어느 정도 자원을 사용하고 있었는지를 확인할 수 있습니다.
표 2는 각각의 방법의 주된 특징과 메리트/디메리트를 집계한 것입니다.어느 쪽을 사용할까는 튜닝의 목적 취득하는 환경에 맞추어 선택하시면 됩니다.
|
|
동적 퍼포먼스뷰 |
SQL 트레이스 |
|
조사 가능한 SQL |
・현재 공유 SQL영역에 캐쉬되어 있는 SQL |
・세션으로 실행된 모든 SQL |
|
주로 확인할 수 있는 항목 |
- SQL |
- SQL |
|
메리트 |
・어플리케이션의 처리 속도에 대한 영향이 적다 |
・어플리케이션중에서 실행되고 있는 각 SQL에 관해서 상세한 정보를 취득 가능 |
|
디메리트 |
・1회당의 실행 시간 등은 평균치 밖에 취득할 수 없다 |
・트레이스의 취득, 파일에의 기입에 수반하는 오버헤드가 있다 |
|
표 2 동적 파포만스뷰와 SQL 트레이스의 차이 | ||
![]() |
|
그림 1 V$SQL와 SQL 트레이스의 사용구분 |
①v$SQL을 검색
메모리상의 전SQL정보(SQL1-SQL5)를 참조
②SQL 트레이스를 취득
이 세션에 SQL트레이스를 설정해 SQL4,SQL5를 실행
■ 동적 성능뷰를 사용한 SQL문 걸러내기
문제가 있을 법한 SQL을 걸러내기 위해서 사용하는 동적 성능뷰는 주로 V$SQL, V$SQL_TEXT, V$SQL_PLAN의 3개로 이것들은 공유 SQL 영역에 보관 유지되고 있는 SQL의 정보를 표시합니다.이 공유 SQL 영역은 SQL를 재이용하기 위한 정보가 캐쉬되는 영역이 됩니다. 실행된 SQL의 정보는 반드시 이 영역에 캐쉬됩니다만 빈영역이 부족하게 되었을 경우 새로운 SQL를 위해서 실행 빈도가 낮은 SQL의 정보를 메모리에서 내려버립니다. 그 때문에 이 방법은 지금까지 실행된 모든 SQL의 정보를 취득할 수 있는 것은 아닌 점에 주의하삼.
필요한 정보는 직접 SELECT문으로 확인할 수도 있고 또, 일부의 정보는 Oracle가 표준으로 제공하고 있는 STATSPACK 유틸리티 , AWR를 사용하여 취득가능
표 3은, SQL 조사에 사용하는 V$ 테이블의 열명, 의미입니다. 여기서 소개한 V$SQL_PLAN는 실행 계획을 확인하는 뷰이므로 다음에 설명합니다.
|
뷰명 |
주된 격납 정보 |
주된 열명 |
열값의 의미 |
|
V$SQL |
・SQL의 선두1000bytes |
SQL_TEXT |
SQL의 선두 1000bytes |
|
SORTS |
SORT의 회수 | ||
|
FETCHES |
FETCH의 회수 | ||
|
EXECUTIONS |
실행 회수 | ||
|
USERS_EXECUTING |
현재 실행중의 유저수 | ||
|
PARSE_CALLS |
해석 콜의 회수 | ||
|
DISK_READS |
디스크 읽기수 | ||
|
BUFFER_GETS |
버퍼 읽기수 | ||
|
ROWS_PROCESSED |
SQL가 되돌리는 행수 | ||
|
CPU_TIME |
처리에 사용한 CPU 시간(마이크로 세컨드) | ||
|
ELAPSED_TIME |
처리에 사용한 경과시간(마이크로 세컨드) | ||
|
ADDRESS |
다른 View와의 결합에 사용 | ||
|
HASH_VALUE |
다른 View와의 결합에 사용 | ||
|
V$SQL_TEXT |
・SQL의 전문 |
SQL_TEXT |
64 bytes 단위로 분할된 SQL |
|
PIECE |
분할된 SQL의 단편 번호 | ||
|
ADDRESS |
다른 View와의 결합에 사용 | ||
|
HASH_VALUE |
다른 View와의 결합에 사용 | ||
|
V$SQL_PLAN |
・SQL의 실행 계획 |
OBJECT_NAME |
실행 계획중의 테이블, 색인명 |
|
OPERATION |
실행 계획 오퍼레이션 | ||
|
OPTIONS |
실행 계획 오퍼레이션의 옵션 | ||
|
OPTIMIZER |
옵티마이져 모드 | ||
|
DEPTH |
실행 계획의 Tree의 깊이 | ||
|
ADDRESS |
다른 View와의 결합에 사용 | ||
|
HASH_VALUE |
다른 View와의 결합에 사용 | ||
|
표 3 SQL의 조사에 사용하는 주된 V$테이블 | |||
◆ 합계 실행 시간이 긴 SQL 추출
V$SQL를 참조해 대상이 되는 SQL를 걸러내려면 리스트 1에 나타낸 SQL를 실행합니다. ORDER BY구의 조건을 변경해 목적에 맞추어 걸러낼 조건을 변경합니다. 합계 실행 시간이 긴 SQL를 밝혀내는 경우에는 ORDER BY구의 조건에“elapsed_time”를 지정합니다. 예에서는 톱 10을 표시하고 있습니다만 맨 마지막 줄의 rownum의 지정을 변경해 출력하는 건수를 변경하시길..
|
|
리스트 1 V$SQL를 참조하는 SQL |
|
|
리스트 2 합계 실행 시간의 긴 SQL의 출력예 |
출력예를 보면 ELAPSED_TIME열의 값이 「186.913533초」인 것을 확인할 수 있습니다. 이 SQL는 EXECUTIONS가 3 이기 때문에 1회의 실행 당 약 62초 (≒186.91353/3) 걸렸다고 추측됩니다.
◆ 버퍼 읽기 블록수가 많은 SQL
버퍼 읽기수에 관해서는 한번 실행 당 읽기수와 누적 읽기수의 2개의 관점으로부터 조사합니다.
한번 실행 당 버퍼 읽기수가 많은 SQL를 밝혀내는 경우는 ORDER BY구의 조건에 buffer_gets/executions를하고 누적 읽기수가 많은 SQL를 밝혀내는 경우는 ORDER BY구의 조건에 buffer_gets 를 지정합니다. STATSPACK 리포트에서는 SQL statements ordered by buffer gets 섹션의 출력에 해당하는 정보가 됩니다.
대량의 버퍼 읽기를 실시하고 있는 SQL는 적절치 않은 색인이나 연결 색인의 일부를 사용하고 있을 가능성이 있습니다.
이하의 출력예는, buffer_gets를 지정한 결과입니다.
|
|
리스트 3 버퍼 읽기 블록수가 많은 SQL의 출력예 |
출력예를 보면, BUFFER_GETS열의 값으로 누적 읽기수 (96300), 한번 실행 당의 읽기수가 (24075)라 확인 할수 있습니다.
◆ 디스크 읽기 블록수가 많은 SQL
디스크 읽기수가 많은 SQL를 밝혀내는 경우는 ORDER BY구의 조건에 “disk_reads”를 지정합니다. STATSPACK의 리포트의 「SQL ordered by Reads for DB」섹션의 출력에 해당합니다.
디스크 읽기가 다발하고 있는 경우 효율이 나쁜 색인을 사용하고 있거나 풀 테이블 스캔을 실시하고 있을 가능성을 있습니다. 디스크 I/O는 메모리 I/O와 비교해서 큰폭으로 처리 속도가 떨어지므로 튜닝에 의해 디스크 I/O를 줄일 수 없는가 검토해야 합니다.
|
|
리스트 4 디스크 읽기 블록수가 많은 SQL의 출력예 |
출력예를 보면 DISK_READS열의 값이 (291138), 한번 실행 당 DISK_READS의 값을 나타내는 DISK_PER_RUN열의 값도 (291138) 인 것을 확인할 수 있습니다.
데이타베이스의 기동 후, 처음으로 그 데이터에 액세스 한 경우는 반드시 디스크에서 읽어 들여야 합니다. 이 때문에 이러한 정보는 기동 후 어느 정도 시간이 경과한후 취득하는 것이 좋습니다.
◆실행 회수가 많은 SQL
실행 회수가 많은 SQL를 밝혀내는 경우는 ORDER BY구의 조건에 “executions”를 지정합니다.STATSPACK의 리포트의 「SQL ordered by Executions for DB」섹션의 출력에 해당합니다.
실행 회수가 많은 SQL는 1회의 실행으로 액세스 하는 블록수가 적은 경우라 하더라도 합계를 보면 매우 많은 블록수를 나타내므로 튜닝 대상이 됩니다. 예를 들면 한번 실행으로 20 블록을 스캔 하고 있는 SQL가 10만회 실행되고 있는 경우라면 튜닝으로 블록수를 불과 5 블록만이라도 줄일 수 있다 하더라도 5 블록*10만회에 50만 블록분을 줄일수 있습니다. ORACLE 블록 사이즈가 8 Kbytes의 경우에서는, 4 Gbytes만큼의 논리 읽기를 피할수 있는 계산이 됩니다
|
|
리스트 5 실행 회수가 많은 SQL의 출력예 |
출력예를 보면, EXECUTIONS열의 값이 (791679)이며, 1 실행 당의 읽기수가 (30) 이라고 확인할 수 있습니다. 전체의 읽기 블록수注1에 대한 이 SQL의 읽기 블록수가 많다고 생각할 수 있는 경우는, SQL 튜닝 후보로 합니다
|
注1:전체의 읽기 블록수 |
STATSPACK 리포트에는 지금까지 설명한 섹션 이외에 해석 회수가 많은 SQL(SQL statements ordered by Parse Calls) 공유 메모 리사이즈가 큰 SQL(SQL statements ordered by Sharable Memory), 버젼 카운트가 많은 SQL(SQL statements ordered by Version Count)도 리포트됩니다.
■ SQL 전문의 취득 방법
지금까지 이용해 온 V$SQL 뷰는 SQL의 선두로부터 1000 bytes까지 밖에 표시되지 않았습니다. 1000 bytes를 넘는 긴 SQL를 사용하고 있는 경우에는 V$SQL_TEXT를 참조해 완전한 SQL를 취득하는 것이 가능합니다.
V$SQL로부터 ADDRESS열, HASH_VALUE열의 값을 확인해, 리스트 6의 SQL를 실행합니다.
|
|
리스트 6 전문을 취득하는 SQL의 예 |
|
|
리스트 7 SQL를 전문 출력한 출력예 |
◇
이번회에서는 튜닝 대상의 SQL를 동적 성능뷰를 통해 걸러내는 방법을 설명했습니다.다음 회에서는 SQL 트레이스 실행 계획의 취득 방법과 그 견해에 대해 설명합니다.

댓글 없음:
댓글 쓰기