728x90
1.1 SQL 파싱과 최적화
1.1.1 구조적 집합적 선언적 질의 언어
- 용어
- sql: structured Query Language (구조적 질의 언어)
- 사용자 → 옵티마이저 → 프로시저
- sql 옵티마이저 : 프로시저를 만들어내는 dmbs 내부 엔진 == 프로그래밍을 대신해 주는 역할
- SQL 최적화 : DBMS 내부에서 프로시저를 작성하고 컴파일해서 실행 가능한 상태로 만드는 전 과정
1.1.2 SQL 최적화
- sql 최적화 과정 세분화
- SQL 파싱 (sql 파서)
- 파싱 트리 생성 : sql문을 이루는 개별 구성요소를 분석해서 파싱 트리 생성
- syntax 체크 : 문법적 오류가 없는지 확인
- semantic 체크 : 의미상 오류가 없는지 확인
- SQL 최적화 (옵티마이저) - 1.1.3 자세한 설명
- 옵티마이저가 역할 수행 : sql 옵티마이저는 미리 수집한 시스템 및 오브젝트 통계정보를 바탕으로 다양한 실행경로를 생성해서 비교한 후 가장 효율적인 하나를 선택
- 로우 소스 생성 (로우 코드 생성기)
- sql 옵티마이저가 선택한 실행경로를 실제 실행 가능한 코드 또는 프로시저 형태로 포맷팅하는 단계
- SQL 파싱 (sql 파서)
1.1.3 SQL 옵티마이저
- sql 옵티마이저
- 사용자가 원하는 작업을 가장 효율적으로 수행할 수 있는 최적의 데이터 액세스 경로를 선택해 주는 DBMS 핵심 엔진
- 참고
- sql 옵티마이저는 sql 파서, 로우 소스 생성기와 같이 서버 프로세스가 가진 기능일 뿐이다.
- 백그라운드 프로세스가 아니다. 백그라운드 프로세스: dbwr, lgwr, pmon, smon
1.1.4 실행계획과 비용
- 실행계획을 잘 읽을 줄 알아야 한다.
- dbms에도 sql 실행경로 미리보기 기능이 있다. 실행계획이 바로 그것이다.
- sql 옵티마이저가 생성한 처리절차를 개발자가 확인 할 수 있게 트리 구조로 표현한 것이 실행계획
- 토드나 오렌지 같은 쿼리 툴을 사용
실행계획 예시
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=209 Card=5 Bytes=175)
1 0 TABLE ACCESS (BY INDEX ROWID) OF ’ EMP' (Cost=2 Card=5 Bytes=85)
2 1 NESTED LOOPS (Cost=209 Card=5 Bytes=175)
3 2 TABLE ACCESS (BY INDEX ROWID) OF ’ DEPT ’ (Cost=207 Card=1 Bytes=18)
4 3 INDEX (RANGE SCAN) OF 'DEPT_LOC_IDX ’ (NON-UNIQUE) (Cost=7 Card=1)
5 2 INDEX (RANGE SCAN) OF ’ EMP_DEPTNO_IDX ’ (NON-UNIQUE) (Cost=1 Card=5)
- 옵티마이저가 T_X01 인덱스를 선택한 근거 = 비용
- 비용 : 쿼리를 수행하는 동안 발생할 것으로 예상하는 I/O 횟수 또는 예상 소요시간을 표현한 값
- 주의 : 비용은 어디까지나 예상시간이기 때문에 수동으로도 설정할 줄 알아야한다.
1.1.5 옵티마이저 힌트
- 힌트 사용법 : 주석 기호에 ‘+’를 붙이기
- SELECT FROM WHERE /*+ INDEX(A 고객_PK) */ 고객명/ 연락처/주소/가입일시 고객 A 고객ID= ’000000008'
- 주의 사항 존재
1.2 SQL 공유 및 재사용
1.2.1 소프트 파싱 vs 하드 파싱
- SGA(system global area)
- 서버 프로세스와 백그라운드 프로세스가 공통으로 액세스하는 데이터와 제어 구조를 캐싱하는 메모리 공간
- 라이브러리 캐시 : sql 파싱, 최적화, 로우 소스 생성과정을 거쳐 생성한 내부 프로시저를 캐시 한 것
- db 캐시 : table data를 캐시한 것
- 소프트 파싱 : sql을 캐시에서 찾아 곧바로 실행단계로 넘어가는 것
- 하드 파싱 : 소프트 파싱 실패해서 ‘파싱, 최적화, 로우 소스 생성’ 단계까지 모두 거치는 것
1.2.2 바인드 변수의 중요성
- 이름없는 sql 문제
- sql은 이름이 따로 없다.
- sql 자체가 이름이기 때문에 텍스트 중 작은 부분이라도 수정되면 그 수간 다른 객체로 생성되는 문제점을 가진다.
- 일회성 및 무효화된 sql까지 모두 저장하려면 많은 공간이 필요하고, 그만큼 sql을 찾는 속도도 느려진다. 따라서 sql을 영구 저장하지 않는 쪽을 선택한다.
- 공유 가능 sql
- sql을 찾기 위해 사용하는 키 값 = sql 문 그 자체
- 의미적으로 모두 같지만, 실행할 때 각각 최적화를 진행하고 라이브러리 캐시에서 별도 공간을 사용한다.
- SELECT * FROM CUSTOMER WHERE LOGIN_ID = ?
- ? : 바인딩 변수 - 성능 , 보안
- 매개 변수가 있는 함수
- prepared statement
1.3 데이터 저장 구조 및 I/O 메커니즘
1.3.1 SQL이 느린 이유
- 99% I/O 때문
- sql 쿼리가 I/O를 찾는 동안 process가 멈춤상태로 존재한다. 쓰레드
1.3.2 데이터베이스 저장 구조
- 테이블 스페이스 - 세그먼트 - 익스텐트 - 블록 - 로우
- 블록 : 데이터를 읽고 쓰는 단위
- 블록 1개 : 하나의 테이블이 독점, 한 블록에 저장된 레코드는 모두 같은 테이블 레코드다
- 익스텐트 : 공간을 확장하는 단위, 연속된 블록 집합
- 익스텐트 1개 : 하나의 테이블이 독점 == 한 익스텐트에 담긴 블록은 모두 같은 테이블 블록
- 세그먼트 : table space를 object 종류에 따라 나눈 것
- 테이블 스페이스 : 모든 object 저장하는 공간, 여러개 데이터 파일
- 데이터 파일 : 디스크 상의 물리적인 OS 파일
- 참고
- 블록 == 페이지
- 세그먼트에 할당된 모든 익스텐트가 같은 데이터파일에 위치하지 않을 수 있다.
- DBA(data block address)
- 모든 데이터 블록은 디스크 상에서 몇 번 데이터 파일의 몇번째 블록인지를 나타내는 자신만의 고유 주소값를 DBA 라고 한다.
- 인덱스를 이용해 테이블 레코드를 읽을 때는 인덱스 rowid 이용
- rowid : dba + 로우 번호(블록 내 순번)
- table 스캔 할 때 테이블 세그먼트 헤더에 저장된 익스텐트 맵을 이용
1.3.3 블록 단위 I/O
- 한번 읽을 때 8k 씩 읽는다.
1.3.4 시퀀셜 액세스 vs 랜덤 액세스
테이블 또는 인덱스 블록 을 읽는 방식
- 시퀀셜 액세스 : 논리적 또는 물리적으로 연결된 순서에 따라 차례대로 블록을 읽는 방식
- 블록간에 서로 논리적인 연결고리를 갖고 있지 않는데 시퀀셜 방식으로 액세스 할 수 있는 이유?
- 세그먼트 헤더에 map 으로 세그먼트에 할당된 익스텐트 목록을 관리 = 익스텐트 맵
- 익스텐트 맵 은 각 익스텐드의 첫 번째 블록 주소 값을 가짐
- 각 익스텐트의 첫 번째 블록 뒤에 연속해서 저장된 블록을 순서대로 읽으면, 이게 full table scan
- 블록간에 서로 논리적인 연결고리를 갖고 있지 않는데 시퀀셜 방식으로 액세스 할 수 있는 이유?
- 랜덤 액세스 : 논리적, 물리적인 순서를 따르지 않고, 레코드 하나를 읽기 위해 한 블록씩 접근하는 방식
1.3.5 논리적 I/O vs 물리적 I/O
- 데이터 블록을 읽을 땐 항상 버퍼캐시부터 탐색
- 없을시, I/O 뒤짐
1.3.6 Single Block I/O vs Multiblock I/O
- 데이터를 모두 캐시에 적재할 수 없기 때문에 디스크에서 받아와서 적재를 해야한다.
- 읽고 적재하는 방식 2가지
- Single block : 한 번에 한 블록씩 요청해서 메모리에 적재하는 방식
- 인덱스를 이용할 때 기본적으로 인덱스와 테이블 블록 모두 single block 방식 사용
- Muliti block : 한 번에 여러 블록씩 요청해서 메모리에 적재하는 방식
- Single block : 한 번에 한 블록씩 요청해서 메모리에 적재하는 방식
1.3.7 Table Full Scan vs Index Range Scan
- 테이블에 저장된 데이터를 읽는 2가지 방식
- table full scan
- index range scan
과목 : 친절한 sql 튜닝
1단원 sql 처리과정과 i/o
1.1.2 sql 파싱과 최적화
sql 최적화
- sql 파싱
- 파싱 트리 생성
- syntax 체크
- semantic 체크
- sql 최적화 : 통계 정보 바탕으로 다양한 실행경로를 생성해서 비교후 가장 효율적인 하나를 선택, db 성능을 결정하는 가장 핵심적인 엔진
- 로우 소스 생성
1.1.3 sql 옵티마이저
dbms에도 sql 실행경로 미리보기 기능이 존재, 실행계획이 바로 그것, sql 옵티마이저가 생성한 처리절차를 사용자가 확인할 수 있게 아래와 같이 트리 구조로 표현한 것
1. SQL 처리과정과 I/O
1.1 SQL 파싱과 최적화
1.1.1 구조적 집합적 선언적 질의 언어
- 용어
- sql: structured Query Language (구조적 질의 언어)
- 사용자 → 옵티마이저 → 프로시저
- sql 옵티마이저 : 프로시저를 만들어내는 dmbs 내부 엔진 == 프로그래밍을 대신해 주는 역할
- SQL 최적화 : DBMS 내부에서 프로시저를 작성하고 컴파일해서 실행 가능한 상태로 만드는 전 과정
1.1.2 SQL 최적화
- sql 최적화 과정 세분화
- SQL 파싱 (sql 파서)
- 파싱 트리 생성 : sql문을 이루는 개별 구성요소를 분석해서 파싱 트리 생성
- syntax 체크 : 문법적 오류가 없는지 확인
- semantic 체크 : 의미상 오류가 없는지 확인
- SQL 최적화 (옵티마이저) - 1.1.3 자세한 설명
- 옵티마이저가 역할 수행 : sql 옵티마이저는 미리 수집한 시스템 및 오브젝트 통계정보를 바탕으로 다양한 실행경로를 생성해서 비교한 후 가장 효율적인 하나를 선택
- 로우 소스 생성 (로우 코드 생성기)
- sql 옵티마이저가 선택한 실행경로를 실제 실행 가능한 코드 또는 프로시저 형태로 포맷팅하는 단계
- SQL 파싱 (sql 파서)
1.1.3 SQL 옵티마이저
- sql 옵티마이저
- 사용자가 원하는 작업을 가장 효율적으로 수행할 수 있는 최적의 데이터 액세스 경로를 선택해 주는 DBMS 핵심 엔진
- 참고
- sql 옵티마이저는 sql 파서, 로우 소스 생성기와 같이 서버 프로세스가 가진 기능일 뿐이다.
- 백그라운드 프로세스가 아니다. 백그라운드 프로세스: dbwr, lgwr, pmon, smon
1.1.4 실행계획과 비용
- 실행계획을 잘 읽을 줄 알아야 한다.
- dbms에도 sql 실행경로 미리보기 기능이 있다. 실행계획이 바로 그것이다.
- sql 옵티마이저가 생성한 처리절차를 개발자가 확인 할 수 있게 트리 구조로 표현한 것이 실행계획
- 토드나 오렌지 같은 쿼리 툴을 사용
실행계획 예시
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=209 Card=5 Bytes=175)
1 0 TABLE ACCESS (BY INDEX ROWID) OF ’ EMP' (Cost=2 Card=5 Bytes=85)
2 1 NESTED LOOPS (Cost=209 Card=5 Bytes=175)
3 2 TABLE ACCESS (BY INDEX ROWID) OF ’ DEPT ’ (Cost=207 Card=1 Bytes=18)
4 3 INDEX (RANGE SCAN) OF 'DEPT_LOC_IDX ’ (NON-UNIQUE) (Cost=7 Card=1)
5 2 INDEX (RANGE SCAN) OF ’ EMP_DEPTNO_IDX ’ (NON-UNIQUE) (Cost=1 Card=5)
- 옵티마이저가 T_X01 인덱스를 선택한 근거 = 비용
- 비용 : 쿼리를 수행하는 동안 발생할 것으로 예상하는 I/O 횟수 또는 예상 소요시간을 표현한 값
- 주의 : 비용은 어디까지나 예상시간이기 때문에 수동으로도 설정할 줄 알아야한다.
1.1.5 옵티마이저 힌트
- 힌트 사용법 : 주석 기호에 ‘+’를 붙이기
- SELECT FROM WHERE /*+ INDEX(A 고객_PK) */ 고객명/ 연락처/주소/가입일시 고객 A 고객ID= ’000000008'
- 주의 사항 존재
1.2 SQL 공유 및 재사용
1.2.1 소프트 파싱 vs 하드 파싱
- SGA(system global area)
- 서버 프로세스와 백그라운드 프로세스가 공통으로 액세스하는 데이터와 제어 구조를 캐싱하는 메모리 공간
- 라이브러리 캐시 : sql 파싱, 최적화, 로우 소스 생성과정을 거쳐 생성한 내부 프로시저를 캐시 한 것
- db 캐시 : table data를 캐시한 것
- 소프트 파싱 : sql을 캐시에서 찾아 곧바로 실행단계로 넘어가는 것
- 하드 파싱 : 소프트 파싱 실패해서 ‘파싱, 최적화, 로우 소스 생성’ 단계까지 모두 거치는 것
1.2.2 바인드 변수의 중요성
- 이름없는 sql 문제
- sql은 이름이 따로 없다.
- sql 자체가 이름이기 때문에 텍스트 중 작은 부분이라도 수정되면 그 수간 다른 객체로 생성되는 문제점을 가진다.
- 일회성 및 무효화된 sql까지 모두 저장하려면 많은 공간이 필요하고, 그만큼 sql을 찾는 속도도 느려진다. 따라서 sql을 영구 저장하지 않는 쪽을 선택한다.
- 공유 가능 sql
- sql을 찾기 위해 사용하는 키 값 = sql 문 그 자체
- 의미적으로 모두 같지만, 실행할 때 각각 최적화를 진행하고 라이브러리 캐시에서 별도 공간을 사용한다.
- SELECT * FROM CUSTOMER WHERE LOGIN_ID = ?
- ? : 바인딩 변수 - 성능 , 보안
- 매개 변수가 있는 함수
- prepared statement
1.3 데이터 저장 구조 및 I/O 메커니즘
1.3.1 SQL이 느린 이유
- 99% I/O 때문
- sql 쿼리가 I/O를 찾는 동안 process가 멈춤상태로 존재한다. 쓰레드
1.3.2 데이터베이스 저장 구조
- 테이블 스페이스 - 세그먼트 - 익스텐트 - 블록 - 로우
- 블록 : 데이터를 읽고 쓰는 단위
- 블록 1개 : 하나의 테이블이 독점, 한 블록에 저장된 레코드는 모두 같은 테이블 레코드다
- 익스텐트 : 공간을 확장하는 단위, 연속된 블록 집합
- 익스텐트 1개 : 하나의 테이블이 독점 == 한 익스텐트에 담긴 블록은 모두 같은 테이블 블록
- 세그먼트 : table space를 object 종류에 따라 나눈 것
- 테이블 스페이스 : 모든 object 저장하는 공간, 여러개 데이터 파일
- 데이터 파일 : 디스크 상의 물리적인 OS 파일
- 참고
- 블록 == 페이지
- 세그먼트에 할당된 모든 익스텐트가 같은 데이터파일에 위치하지 않을 수 있다.
- DBA(data block address)
- 모든 데이터 블록은 디스크 상에서 몇 번 데이터 파일의 몇번째 블록인지를 나타내는 자신만의 고유 주소값를 DBA 라고 한다.
- 인덱스를 이용해 테이블 레코드를 읽을 때는 인덱스 rowid 이용
- rowid : dba + 로우 번호(블록 내 순번)
- table 스캔 할 때 테이블 세그먼트 헤더에 저장된 익스텐트 맵을 이용
1.3.3 블록 단위 I/O
- 한번 읽을 때 8k 씩 읽는다.
1.3.4 시퀀셜 액세스 vs 랜덤 액세스
테이블 또는 인덱스 블록 을 읽는 방식
- 시퀀셜 액세스 : 논리적 또는 물리적으로 연결된 순서에 따라 차례대로 블록을 읽는 방식
- 블록간에 서로 논리적인 연결고리를 갖고 있지 않는데 시퀀셜 방식으로 액세스 할 수 있는 이유?
- 세그먼트 헤더에 map 으로 세그먼트에 할당된 익스텐트 목록을 관리 = 익스텐트 맵
- 익스텐트 맵 은 각 익스텐드의 첫 번째 블록 주소 값을 가짐
- 각 익스텐트의 첫 번째 블록 뒤에 연속해서 저장된 블록을 순서대로 읽으면, 이게 full table scan
- 블록간에 서로 논리적인 연결고리를 갖고 있지 않는데 시퀀셜 방식으로 액세스 할 수 있는 이유?
- 랜덤 액세스 : 논리적, 물리적인 순서를 따르지 않고, 레코드 하나를 읽기 위해 한 블록씩 접근하는 방식
1.3.5 논리적 I/O vs 물리적 I/O
- 데이터 블록을 읽을 땐 항상 버퍼캐시부터 탐색
- 없을시, I/O 뒤짐
1.3.6 Single Block I/O vs Multiblock I/O
- 데이터를 모두 캐시에 적재할 수 없기 때문에 디스크에서 받아와서 적재를 해야한다.
- 읽고 적재하는 방식 2가지
- Single block : 한 번에 한 블록씩 요청해서 메모리에 적재하는 방식
- 인덱스를 이용할 때 기본적으로 인덱스와 테이블 블록 모두 single block 방식 사용
- Muliti block : 한 번에 여러 블록씩 요청해서 메모리에 적재하는 방식
- Single block : 한 번에 한 블록씩 요청해서 메모리에 적재하는 방식
1.3.7 Table Full Scan vs Index Range Scan
- 테이블에 저장된 데이터를 읽는 2가지 방식
- table full scan
- index range scan