데이터베이스2025. 3. 2. 14:26

SQLP : 제3과목은 SQL 고급활용 및 튜닝 이다.

 

 

3과목. SQL 고급활용 및 튜닝

1. SQL 수행 구조
2. SQL 분석 도구
3. 인덱스 튜닝
4. 조인 튜닝
5. SQL 옵티마이저
6. 고급 SQL 튜닝
7. Lock과 트랜잭션 동시성 제어

 

 

 

 

 

실행계획 표시

 

DBMS_XPLAN.DISPLAY
- 단일 SQL문에 대해 "예측" 실행계획

explain plan for
SELECT * FROM Product WHERE ProductID = 1;

select * from table(dbms_xplan.display(null, null, 'typical'));

 

 

TYPICAL 포맷

--------------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |       1 |      20 |       1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |       1 |      20 |       1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN        | PK_EMP |       1 |         |       1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("EMPNO"=7900)

14 rows selected.

 

 

ALL 포맷

--------------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |       1 |      20 |       1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |       1 |      20 |       1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN        | PK_EMP |       1 |         |       1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / EMP@SEL$1
   2 - SEL$1 / EMP@SEL$1
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("EMPNO"=7900)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "EMPNO"[NUMBER,22], "ENAME"[VARCHAR2,10]
   2 - "EMP".ROWID[ROWID,10], "EMPNO"[NUMBER,22]
 
26 rows selected.

 

 

 

DBMS_XPLAN.DISPLAY_CURSOR
- 단일 SQL문에 대해 "실제" 수행된 실행계획

 

ALTER SESSION SET STATISTICS_LEVEL = ALL;
SELECT * FROM Product WHERE ProductID = 1;
SELECT * FROM TABLE(dbms_xplan.display_cursor(null, null, 'typical');


SELECT /*+ gather_plan_statistics */ * FROM Product WHERE ProductID = 1;
SELECT * FROM TABLE(dbms_xplan.display_cursor(null, null, 'allstats last');

 

 

TYPICAL 포맷

--------------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |         |         |       1 (100)|         |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |       1 |      20 |       1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN        | PK_EMP |       1 |         |       1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("EMPNO"=7900)
 
 
20 rows selected.

 

 

ALL 포맷

--------------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |         |         |       1 (100)|         |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |       1 |      20 |       1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN        | PK_EMP |       1 |         |       1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / EMP@SEL$1
   2 - SEL$1 / EMP@SEL$1
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("EMPNO"=7900)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "EMPNO"[NUMBER,22], "ENAME"[VARCHAR2,10]
   2 - "EMP".ROWID[ROWID,10], "EMPNO"[NUMBER,22]
 
 
32 rows selected. 

 

 

 

Id
실행계획에서의 구분자
Operation
각 단계에서의 어떤 작업이 일어났는지 표시
Name
테이블명이나 index 명을 표시함
Rows
해당 쿼리 계획 단계에서 나올 것으로 예상되는 행의 수
Byte
실행 계획의 각 단계가 반환할 것으로 예상 되는 데이터의 크기를 바이트로 나타낸 수. 이 수는 행의 수와 행의 예상 길이에 따라 결정됨
Cost
CBO가 쿼리 계획의 각 단계에 할당한 비용. CBO는 동일한 쿼리에 대해 다양한 실행 경로/계획을 생성하며 모든 쿼리에 대해 비용을 할당함
위의 실행 계획에선 전체 비용이 13인것을 알수 있음
Time
각 단계별 수행 시간
Query Block Name
SQL 문장을 Query Block이라는 단위로 나눔. inline view 와 subquery 등
Outline Data
실행 계획을 수립 하는데 필요한 내부적으로 적용된 Hint들의 목록
Predicate
조건절
Column Projection
실행 계획의 특정 단계에서 어떤 Column을 추출하는가를 의미

 

 

 

ADVANCED ALLSTATS LAST 포맷

 

 

Starts
말 그대로 해당 오퍼레이션이 "시작"된 횟수를 의미함
이 개념은 Nested Loops Join을 생각하시면 쉽게 이해할 수 있음 
Nested Loops Join은 선행 테이블에서 읽는 로우수만큼 후행 테이블을 탐색하는 구조임 
만일 선행 테이블에서 100건이 나온다면 후행 테이블을 100번 액세스하게됨
이럴 경우에 후행 테이블에서 대한 읽기 작업의 Starts 값이 "100"이 되는것
E-Rows / E-Bytes / E-Time
예측값
A-Rows / A-Time
실제 실행된 값

 

 

 

 

 

SQL 트레이스

- SQL Trace는 실행되는 SQL문의 실행통계를 세션별로 모아서 Trace 파일을 만듬
- SQL Trace는 세션과 인스턴스 레벨에서 SQL문장들을 분석할 수 있음
- .trc 파일로 저장되고, tkprof 유틸리티를 이용하면 분석

 

 

 

call 커서 상태에 따라 Parse, Execute, Fetch 세 개의 Call로 나누어 각각에 대한 통계정보를 보여준다.
Parse 커서를 파싱하고 실행계획을 생성하는 데 대한 통계
Execute 커서의 실행 단계에 대한 통계
Fetch 레코드를 실제로 Fetch하는데 대한 통계
count Parse, Execute, Fetch 각 단계가 수행된 횟수
cpu 현재 커서가 각 단계를 수행하는 데 소요된 시간
Elapsed Time CPU Time + Wait Time = Response시점 - Call 시점
CPU 시간에 비해 Elapsed 시간이 현저히 큰 경우는 디스크 I/O 때문이다.
disk 디스크로부터 읽은 블록 수
query Consistent 모드에서 읽은 버퍼 블록 수
current Current모드에서 읽은 버퍼 블록 수
rows 각 단계에서 읽거나 갱신한 처리건 수
Misses in library cache during parse Parse 구간에서 해당 SQL을 Library Cache에서 읽지 못하고 잃어버린 횟수
값이 1이면 Hard Parse, 0이면 Soft Parse를 의미함
Optimizer mode 옵티마이저 모드

 

 

 

 

버퍼캐시 히트율

(1 - disk / (query+current)) * 100
또는
( (query+current) -disk) / (query+current) * 100

 

 

 

Row Source Operation 통계 출력

 

 

Rows
각 수행단계에 출력된 row수
Cr
consistent 모드 블록 읽기
Pr(r)
디스크 블록 읽기
Pw(w)
디스크 블록 쓰기
Time
소요시간(us= microsecond)
Cost
Cost Based Optimizer(CBO)에서 예측한 비용
Size
리턴한 데이터 size(bytes)
Card
Cardinality, Cost Based Optimizer(CBO)에서 예측한 row수

 

 

 

 

현재 세션에 SQL 트레이스 거는 방법

 

alter session set sql_trace = true;

select 절;

=> .trc 파일이 생성됨

 

 

 

AutoTrace
- SQL Plus에서 실행계획을 가장 쉽고 빠르게 확인해 볼 수 있는 방법

 

grant plustrace to scott;
- plustrace 권한부여
set autotrace on
- SQL 실제 수행 => SQL 실행결과, 실행계획 및 실행통계 출력
set autotrace on explain
- SQL 실제 수행 => SQL 실행결과, 실행계획 출력
set autotrace on statistics
- SQL 실제 수행 => SQL 실행결과, 실행통계 출력
set autotrace traceonly
- SQL 실제 수행 => 실행계획 및 실행통계 출력
set autotrace traceonly explain
- SQL 실제 수행 X => 실행계획 출력
set autotrace traceonly statistics
- SQL 실제 수행 => 실행통계 출력

 

--------------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |       1 |      20 |       1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |       1 |      20 |       1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN        | PK_EMP |       1 |         |       1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("EMPNO"=7900)

 

 

통계

Statistics
----------------------------------------------------------
      1  recursive calls
      0  db block gets
      2  consistent gets
      0  physical reads
      0  redo size
    596  bytes sent via SQL*Net to client
    523  bytes received via SQL*Net from client
      2  SQL*Net roundtrips to/from client
      0  sorts (memory)
      0  sorts (disk)
      1  rows processed

 

recursive calls
사용자의 SQL문을 실행하기 위하여 수행된 SQL 문의 수
db block gets
현재 모드(current mode)에서 버퍼 캐시로부터 읽어온 블록의 총 수
consistent gets
버퍼 캐시의 블록에 대한 일관된 읽기의 요청 횟수. 일관된 읽기는 언두 정보, 즉 롤백 정보에 대한 읽기를 요구할 수도 있으며 이들 언두에 대한 읽기도 계산됨
physical reads
물리적으로 데이터 파일을 읽어 버퍼 캐시에 넣은 횟수
redo size
해당 문이 실행되는 동안 생성된 리두의 전체 크기를 바이트 단위로 나타낸 수
byte sent via SQL*Net to client
서버로부터 클라이언트에 전송된 총 바이트 수
byte recevied via SQL*Net from client
클라이언트로부터 받은 총 바이트 수
SQL*Net roundtrips to/from client
클라이언트로(부터) 전송된 SQL*Net 메시지의 총 수. 다중 행 결과 집합으로부터 꺼내오기 위한 왕복을 포함함
sorts(memory)
사용자의 세션 메모리(정렬 영역)에서 수행된 정렬 sort_area_size 데이터베이스 매개변수에 의해 제어됨
sorts(disk)
사용자의 정렬 영역의 크기를 초과하여 디스크(임시 테이블 영역)를 사용하는 정렬
rows processed
수정되거나 select 문으로부터 반환된 행

 

 

 

 

MS-SQL Server

 

트레이스 확인 방법

set statistics profile on
set statistics io on
set statistics time on

- 구문분석 및 컴파일 시간
- 논리직/물리적 읽기 수
- 각 오퍼레이션 단계별 실행 횟수

 

 

set statistics profile on
- 실제 실행계획 표시
Rows : 각 연산자에서 만든 실제의 행 수를 보여줍니다.
Executes : 각 연산자가 몇 번 실행이 되었는지 보여줍니다
StmtText : 세부적으로 어떤 실행이 있었는지를 보여주거나, 실제로 실행된 쿼리를 보여줍니다
Argument : 수행되는 작업의 추가정보를 제공합니다. TOP 절의 행 수나, Group By 조건, Where 조건, Index Seek 혹은 Scan사항 등

 

set statistics io on
- I/O 통계 표시
테이블 'emp'. 스캔 수 1, 논리적 읽기 28, 실제 읽기 0, 페이지 서버 읽기 0, 미리 읽기 읽기 0, 페이지 서버 미리 읽기 읽기 0, lob 논리적 읽기 0, lob 실제 읽기 0, lob 페이지 서버 읽기 0, lob 미리 읽기 읽기 0, lob 페이지 서버 미리 읽기 읽기 0.

 

set statistics time on
- 시간 통계 표시
SQL Server 구문 분석 및 컴파일 시간: 
   CPU 시간 = 0ms, 경과 시간 = 0ms.

(100개 행이 영향을 받음)

 SQL Server 실행 시간: 
 CPU 시간 = 0ms, 경과 시간 = 222ms

 

 

SET SHOWPLAN_ALL ON
또는
SET SHOWPLAN_TEXT ON
- 예상 실행계획 표시

 

 

 

 

 

쿼리별로 실행계획에 나타나는 형태

SELECT distinct / UNION
HASH (UNIQUE)

GROUP BY
HASH (GROUP BY)

ORDER BY
SORT (ORDER BY)

집계함수 SUM(), COUNT()
SORT (AGGREGATE)

윈도우함수 SUM() over(partition by xx)
WINDOW (SORT)

ROWNUM 사용시
COUNT (STOPKEY)

 

 

Response Time Analysis 방법론
- 세션 또는 시스템 전체에 발생하는 병목 현상과 그 원인을 찾아 문제를 해결하는 방법
- CPU time과 Wait time을 각각 break down하면서 서버의 일량과 대기 시간을 분석

Response Time = Servic Time + Wait Time
또는
Response Time = CPU time + Queue Time

 

 

AWR (Automatic Workload Repository) 보고서
- DB 의 상태를 진단하는 정보
- DBA에게 데이터베이스 실행 시간과 관련된 스냅샷과 상세한 정보를 제공
- Statpack 을 업그레이드 해서 개발 되었다.

 

 

DB 대기 이벤트 및 통계 정보
- 시스템 통계 정보
- 데이터베이스 부하 정보
- SQL 수행 정보
- 활동 세션 정보

 

 

Posted by 헝개