728x90
1. Query Plan이란?
- SQL 관계형 데이터베이스 관리 시스템(RDBMS)의 데이터 접근에 사용되는 순서가 있는 단계별 집합
- 엑세스 플랜의 관계형 모델 개념의 특화된 경우
- SQL이 선언형이기 때문에 주어진 쿼리를 실행하기 위해 수많은 방법이 존재하는 것이 일반적이며 이에 따라 다양한 성능 차이를 보임
- Query Optimizer는 Query 실행을 위한 각기 다른 가능성 있는 올바른 플랜 중 일부를 평가한 다음 최적의 옵션을 고려할 때 반환
2. Query Plan 보는 법, 요소(Oracle)
1) Query Plan 보는 법
- 위에서 아래로 내려가면서 제일 먼저 읽을 위치 찾기
- 내려가는 과정에서 같은 들여쓰기가 있으면, 무조건 위에서 아래 순으로 읽기
- 같은 레벨에 들여쓰기된 하위 스텝이 존재하면, 가장 안쪽으로 들여쓰기 된 스텝을 시작으로 상위 스텝으로 읽기
2) Plan 요소
- Cost
- Cost는 누적된 값이며 하위(Child)의 Cost를 Roll Up 함
→ 마지막에 읽는 Cost가 모든 쿼리문에 대한 누적 Cost - 옵티마이저가 측정한 오퍼레이션 수행에 필요한 예측 비용
- 쿼리를 수행함에 있어 사용된 자원이나, 작업의 단위
- 대체로 적을 수록 효율적인 쿼리(좋은 성능)
- Full Scan을 해야 하는 쿼리는 의미가 없을 수도 있음
- cost 수치가 더 높은 질의문이 빠른 경우도 있음
- Cost는 누적된 값이며 하위(Child)의 Cost를 Roll Up 함
- Cardinality
- 행 집합에서 행의 수를 표시(분포도)
- 행 집합은 기본 테이블, 뷰, 조인이나, GROUP BY의 결과
- 행 집합을 의미하니 적게 나타날수록 SQL이 빠를 수 있음
- 옵티마이저가 측정
- Bytes
- 각 실행계획 단계에서 Access된 byte 수를 의미
- 옵티마이저가 측정
3) 비용 계산 방법
- Full table scan
Cost = 전체 블록 수 / DB_FILE_MULTIBLOCK_READ_COUNT의 보정 값
- Unique index scan
Cost = blevel + 1
- Fast Full Index Scan
Cost = leaf_blocks / db_block_size
- Index Range Scan
Cost = blevel + (Selectivity X leaf_blocks) + (Selectivity X Cluster Factor)
- Sort-Merge Join
Cost = (Outer 테이블의 Sort Cost +Inner 테이블의 Sort Cost) -1
- Nest-Loop Join
Cost = Outer 테이블의 Cost + (Inner 테이블의 Cost * Outer 테이블의 Cardinality)
- Hash Join
Cost = (Outer 테이블의 Cost × #Hash 파티선수 +Inner 테이블의 Cost) + 2
3. Oracle
1) Orange,Toad(DB Tool)
실행계획 보는 단축 키 : 쿼리 블록 drag + Ctrl + E
2) Explain plan for
EXPLAIN plan FOR
SELECT *
FROM EMP
WHERE EMPNO > 7600
AND JOB = 'MANAGER'; -- 확인 할 쿼리를 plan table로 저장
SELECT *
FROM TABLE(dbms_xplan.display); -- Plan table 출력
4. MySQL
1) Visual Optimizer(work bench)
쿼리에 대해 돋보기 클릭
2) EXPLAIN
-- 문법
EXPLAIN
쿼리
EXPLAIN
SELECT A.actor_id,
A.first_name,
A.last_name,
B.film_info,
A.last_update
FROM
(
SELECT *
FROM sakila.actor
WHERE last_update > '2023-01-12'
) A
INNER JOIN sakila.actor_info B
ON A.actor_id = B.actor_id
AND A.first_name = B.first_name
AND A.last_name = B.last_name;
- ID
- 실행계획의 순서. 이 순서대로 select 문이 실행
- select_type
- SIMPLE : 단순 select문
- PRIMARY : 첫번째 쿼리
- DERIVED : select문으로 추출된 테이블 ( from 절에서의 서브쿼리 또는 inline view)
- SUBQUERY : sub query 중 첫번째 select문
- UNION : UNION쿼리에서 PRIMARY를 제외한 나머지 select문
- DEPENDENT SUBQUERY
- DEPENDENT UNION
- table
- 대상이 되는 테이블 or alias명
- partitions
- 파티션 사용 시, 대상이 되는 파티션
- type
- data access 타입(우수한 순서대로 적어 둠)
- system : 0개 또는 하나의 row를 가진 테이블. const 타입의 특별한 케이스. (MyISAM, Memory 테이블)
- const : primary key나 unique Key의 모든 컬럼에 대해 equal 조건으로 검색 반드시 1건의 레코드만 반환
- eq_ref : 조인에서 첫 번째 읽은 테이블의 컬럼값을 이용해 두 번째 테이블을 primary key나 unique Key로 equal 조건 검색으로 두번째 테이블은 반드시 1건의 레코드만 반환 (1:1 관계)
- ref : 조인의 순서와 인덱스의 종류와 관계없이 equal 조건으로 검색 (1:n 관계)
- unique_subquery : IN(sub-query) 형태의 조건에서 반환 값에 중복 없음
- index_subquery : unique_subquery와 비슷하지만 반환 값에 중복 있음
- range : 인덱스를 하나의 값이 아니라 범위로 검색. 가장 많이 사용
- Index : 인덱스를 처음부터 끝까지 읽는 인덱스 풀 스캔
- All : 풀스캔. 성능 가장 안 좋음
- data access 타입(우수한 순서대로 적어 둠)
- possible_keys
- 해당 테이블에서 데이터를 찾기위해 선택한 인덱스 목록
- key
- 실제로 쿼리 실행에 사용한 인덱스
- key_len
- 쿼리를 처리하기 위해 단일, 다중 컬럼으로 구성된 인덱스의 각 레코드에서 몇 바이트까지 사용했는지
- ref
- 행을 추출하는데 키와 함께 사용된 컬럼이나 상수 값
- rows
- 쿼리 수행에서 예상하는 검색해야 할 행수. 조인문이나 서브쿼리 최적화에 있어서 중요한 항목.
- 조회 결과 수와 rows가 차이가 크다면 성능 개선 필요
- extra
- 쿼리에 관한 추가적인 정보
- distinct : 이미 처리한 값과 동일한 값을 가진 Row는 처리하지 않음.
- not exist : left join을 수행함에 매치되는 한 행을 찾으면 더 이상 매치되는 행을 검색하지 않음.
- Range checked for each record :사용할 좋은 인덱스가 없음.
- using filesort : 정렬을 위해 추가적인 과정을 필요로 함(물리적인 정렬작업 수행)
- using index : 실제 데이터 Block을 읽지 않고 인덱스 Block 만으로 결과를 생성할 수 있는 경우
- using temporary : 임시 테이블을 사용. order by 나 group by 절이 각기 다른 컬럼을 사용할 때 발생
- using where : where절이 다음 조인에 사용될 행이나 클라이언트에게 돌려질 행을 제한하는 경우
- using index for group-by
- 쿼리에 관한 추가적인 정보
쿼리를 가능한 한 빠르게 하려면, Extra 값의 Using filesort나 Using temporary에 주의해야 함
EXPLAIN의 출력 내용 중 rows 컬럼값들을 곱해봄으로써 얼마나 효과적인 join을 실행하고 있는지 알 수 있음
참조:
728x90
'DataBase > Data & SQL' 카테고리의 다른 글
[Data] 데이터의 종류, 서비스 데이터와 행동 데이터(로그성 데이터) (0) | 2023.04.05 |
---|---|
[Data] 데이터 관리, 마스터 데이터와 MDM(Master Data Management) (0) | 2023.02.12 |
[MySQL] 바이너리 로그(binlog)란? (0) | 2023.01.19 |
[MySQL] MySQL version 확인 방법 (0) | 2023.01.11 |
[SQL] MySQL의 Binding Variables, 바인딩 변수 사용법(mysql,python), 장점 (1) | 2023.01.10 |
댓글