# 부분범위 처리 하시오. = [소트 생략] 하시오
Gorup by도 소트 생략 가능 -> SORT GROUP BY (NO SORT)
인라인뷰 안쪽에 ORDER BY 명시하고 바로 바깥쪽에 ROWNUM <= 조건 명시해야한다.
위처럼 잘 작성하면 TOP N STOPKey 발생하고, 만약 인덱스가 불충분해서 전체 데이터 읽더라고 TOP N Sort 알고리즘 발생하여 소트 부하를 줄여준다.
IN 조건은 소트생략이 불가능하므로 , 아예 필터로 처리하거나 혹은 맨 뒤쪽에 둔다
함수에 스칼라를 씌워버리면 캐싱기능이 작동하여 성능 상승함.
단 입력값의 범위가 작아야함.
DB저장형 함수에 대한 조건절이 필터 조건이면 필터횟수만큼 실행
DB저장형 함수에 대한 조건절이 인덱스 액세스 조건이면 단 1회 수행
인덱스의 범위조건 (Between Like 부등호) 까지가 액세스 조건이고 나머지는 필터 조건이다.
파티션 = 세그먼트
주 파티션, 서브 파티션 체크
상수 조회 -> 정적 파티션 Pruning : 액세스하는 파티션 번호 출력 (ex 3 | 4)
변수 조회 -> 동적 파티션 Pruning : Pstart/Pstop = KEY
파티션 조건절 가공 x
(묵시적 형변환 To_Number, 함수 등 가공하면 모든 파티션 읽음)
묵시적 형변환 때문에 파티션 키 컬럼 형태, 조건절 형태등 세밀히 파악
Global 인덱스는 Prefixed만 지원하므로 인덱스 선두컬럼을 파티션 키가 아닌 Non-Prefixed 형태로 구성하면 에러가 발생.
Intra-Operation-Parallelism : 서로 배타적 범위 독립적으로 동시에 처리 (통신x)
Inter-Operation-Parallelism : 병렬 프로세스 집한간의 통신o
병렬도 4일때 P->P 같이 두개의 서버집합이 처리하면 8개의 병렬 프로세스 필요함. 통신도 필요함. ( Inter )
병렬도 4일때 P->P 이면 필요한 파이프 라인 수는 병렬도의 제곱 = 16개
Full Partition Wise 조인
조인하는 두 테이블이 조인 칼럼에 대해 같은 기준으로 파티셔닝 되어 있으므로 독립적(Intra)으로 조인을 수행하므로
통신 x 병렬도2배 x
Partial Partition Wise 조인
한쪽만 조인칼럼에 대해 파티셔닝 되어있어 나머지 한쪽을 실행 시점에 동적으로 파티셔닝 하고나서 Partition Wise 조인한다.
동적 파티셔닝 과정에서 재분배가 필요하므로 병렬도 2배 필요.
오퍼레이션에서 'PX PARTITION RANGE ALL'이 나타난다면
Full Partition Wise을 수행한 것.
Rownum을 병렬 프로세스들이 처리하면 중복값이 생겨서 QC가 Unique한 값을 생성하기위해 정렬-선택의 과정이 생기므로 병목구간이 발생함.
Rownum보다 ROW_NUMBER() 함수를 사용하여 독립적으로 번호를 부여해야함.
InOut | 스펠링 | 설명 | 통신 | 설계 |
---|---|---|---|---|
SERIAL | (blank) | 시리얼하게 실행 | - | - |
S->P | Parallel_From_Serial | QC가 처리한 결과를 병렬 서버 프로세스에게 전달 | O | 직렬 |
P->S | Parallel_To_Serial | 병렬 서버 프로세스가 처리한 결과를 QC에게 전달 | O | 병렬 |
P->P | Parallel_To_Parallel | 두개의 병렬 서버 프로세스 집합이 처리 지정한 병렬도의 2배만큼 병렬 프로세스 생성 | O | 병렬 |
PCWP | Parallel_Combined_With_Parent | 병렬 프로세스 집합이 현재 스텝과 그 부모 스텝을 모두 처리 | X | 병렬 |
PCWC | Parallel_Combined_With_Child | 병렬 프로세스 집합이 현재 스텝과 그 자식 스텝을 모두 처리 | X | 병렬 |
속성 | - 설명 |
---|---|
Range | - order by또는 sort group by를 병렬로 처리할 때 - 정렬담당인 두 번째 서버 집합의 프로세스마다 처리범위(ex A~G, H~M, T~Z) 지정하고나서, 첫번째 서버집합이 키값에 따라 분배 |
HASH | - 조인이나 Hash Group by를 병렬로 처리할 때 - 해시 함수에 적용하고 리턴값에 따라 전송 - P->P 뿐만아니라 S->P 방식도 이뤄질 수 있다. |
BroadCast | - QC또는 첫 번째 서버 집합에 속한 프로세스들이 각각 읽은 데이터를 두번째 서버 집합에 속한 모든병렬 프로세스에게 전송 - 매우 작은 테이블일때 사용 - P->P 뿐만아니라 S->P 방식도 이뤄질 수 있다. |
KEY | - 특정 칼럼들을 기준으로 테이블 또는 인덱스를 파티셔닝 할때 사용하는 분배방식 |
Round-Robin | - 파티션 키, 정렬 키, 해시 함수등에 의존하지 않고 반대편 병렬 서버에 무작위로 분배 |
PQ_distribute( inner, Outer 분배방식, inner 분배방식)
PQ_distribute (inner, none, none) : 이미 같은 기준으로 파티셔닝 되어 있으므로 바로 Full-Partition Wise Join 시작
PQ_distribute (inner, partition, none) : Partial-Partition Wise Join 유도시 사용되며 Outer테이블을 inner 파티션 기준에 따라 파티셔닝 하라는 뜻
PQ_distribute (inner, none, partition) : Partial-Partition Wise Join 유도시 사용되며 inner테이블을 outer 파티션 기준에 따라 파티셔닝 하라는 뜻
PQ_distribute (inner, hash, hash) : 조인 키 칼럼을 해시 함수에 적용하고 반환값을 기준으로 양쪽 테이블을 동적 파티셔닝 하라는 뜻
동적 파티셔닝 후 Partition Wise Join 수행
PQ_distribute (inner, none, none) : 이미 같은 기준으로 파티셔닝 되어 있으므로 바로 Full-Partition Wise Join 시작
PQ_distribute (inner, broadcast, none) : outer를 브로드 캐스트 하라는 뜻
PQ_distribute (inner, none, broadcast) : inner를 브로드 캐스트 하라는 뜻
항상 관계차수 필수로 확인!!!!!!!!!
UNION / UNION ALL 시 각 집합간, 집합내에서 중복 있는지 체크
서브쿼리가 드라이빙 테이블이 된것은 서브쿼리 안에서 qb_name으로 이름을 지정하고 메인쿼리에서 서브쿼리 이름을 사용해서이다.
ex) qb_name(subq) -> unnest(@subq) leading(@subq) use_nl(@subq)
배치작업이 일어나면 정렬순서를 보장하지 못함 (BCHR != 100%)
SORT ORDER BY 연산이 일어나면 정렬순서 보장 + 부분범위 처리 불가능
트랜잭션의 특징( ACID )
Buffer State
트랜잭션 고립화 수준
For Update문은 Select수행중 Lock을 만나면 같이 진행할 수 없다 NoWait은 Lock 을만나는 순간 에러, Wait 3은 3초간 기다렸다가 에러, 아무것도 없다면 무한정 대기
기본 For Update문은 조인 테이블 모두에게 Lock을 건다
Lock 은 커밋할때까지 유지
인덱스가 없어서 조건절을 만족하는 레코드만 Lock
for update는 테이블에 TM Lock 10g 이하는 RS모드, 11g 이상은 RX 모드
Snapshot too old : 쿼리를 수행하는 동안 발생하는 다른 Transaction들에 의해 UNDO 세그먼트(롤백 세그먼트) 덮어씌워져서 발생한다.
shapshot too old 회피방법
Redo
LGWR이 REDO 로그버퍼를 Redo에 기록하는 시점
Undo
블록원본인 Current Block의 SCN 이 쿼리 SCN 보다 크면
복사본인 CR Block을 생성. CR Block 을 읽을수 있는 레벨까지
Undo를 활용해 과거로 되돌린다.
Wirte Ahead Logging : 버퍼 캐시블록을 갱신하기 전 변경사항을 먼저 Redo 로그 파일에 기록한걸 보장해야함
Log force at Commit : 최소한 커밋할때는 데이터 파일에 써야함
Delayed Block : 커밋시점에 블록을 Cleanout 하지않고 그대로 두엇다가 나중에 해당 블록을 읽는 세션이 이를 정리하도록 하는 것
커밋 절차
뷰Merge가 불가능한 쿼리
소트 오퍼레이션
Null 허용 컬럼은 인덱스 정렬 불가능 (결과집합에 변동가능성)
결합 인덱스에서 Nulls first 시 정렬생략 불가능 (null포함 데이터는 맨뒤에 있기때문)
Oracle
SQL Server
1정규형 : 하나의 속성은 하나의 값만 가진다.
혹은 하나의 엔터티에는 반복되는 속성을 가지지않는다.
2정규형 : 함수적 종속성 제거
일반 속성은 주식별자 전체에 대해 식별되어야 한다.
주식별자(주문번호, 상품번호) 속성(상품명)
3정규형 : 이행함수 종속성 제거
일반 속성이 일반속성에게 식별될때.
반정규화 기법
> 중복칼럼추가 : 여러 테이블에 동일 컬럼 추가
> 파생칼럼추가 : 조회 성능 위해서 미리 계산된 칼럼 추가
> 기능성 칼럼추가 : 최신값 처리하는 이력특성 고려
OLTP 환경이라도 3티어인 클라이언트와 서버 연결을 지속하지 않는 환경(웹 브라우저, 쇼핑몰 등)이라면 최초 응답속도 최적화가 아닌 페이징 처리된 쿼리를 전체 처리속도 최적화가 맞다.
조건절의 In 키워드는 인덱스로 조회시 비효율은 없을 수 있으나 수직탐색을 반복하는 비효율이 존재할 수 있음
Case When C1='none' Then 'false' Else 'true' END
단일행 서브쿼리는 단일행, 다중행 비교 연산자 모두 가능
다중행 서브쿼리는 다중행 연산자만 가능
SQL : 구조적, 집합적, 선언적
선택도 = 조건절 범위 / 전체 범위 (등치 조건)
선택도 = 1 / Distinct Value 갯수 (부등호, Between 조건)
카티널리티 = 총 로우 수 * 선택도
Elapsed time = CPU time + Wait time = Response 시점 - Call 시점
Response Time = Service time + Wait time = CPU time + Queue time
힌트안에 인자끼리는 콤마 사용가능, 힌트끼리는 콤마 x
테이블 지정시 스키마 까지 명시 x
from절에 별칭 사용하면 힌트에 반드시 별칭사용
set arraysize 2;
ROLE을 이용하면 권한 부여와 회수를 쉽게 할 수 있다.
Granule 병렬쿼리 최소단위
Append모드로 insert하면 Exclusive모드의 TM락이 걸린다.
Nologging모드는 Insert문에만 가능하다. (update 불가능)
ArrayProcessing은 Insert into Select 문보다 성능이 떨어짐
delete 문보다 truncate가 redo undo 안쓰므로 효율적임
애플리케이션 커서를 캐싱해야 하드파싱1회로 계속 사용가능
함수형 조건문의 컬럼이 인덱스 액세스 조건이라면 단 1회만 함수실행, 필터조건이라면 건건이 함수 실행
ex) where 생년월일 like '1970%'
and 전화번호 = encryption( :phone);
일때 전화번호가 선두컬럼이어야 1회만 실행됨
List 파티션은 단일 컬럼으로만 파티션 가능
Hash 파티션은 해싱알고리즘으로 파티션 하므로 값이 몰리는 현상 발생할 수 있음. 해결 방법은 분포도를 따져가며 파티션 기준 선정
상수형 조건절은 정적 파티션 Pruning 작동 - 최적화 시점에 미리 결정, 실행계획에는 파티션 번호가 적힘
바인드 변수형 조건절은 동적 파티션 Pruning 작동 - 실행시점
실행계획의 Pstart Pstop에는 Key라고 적힘
index range scan은 파티션 갯수만큼의 병렬도가 최적이다
full scan은 병렬프로세스 DOP가 많으면 많을수록 빠르다
Index Skew : 인덱스 엔트리가 한쪽에 치우치는 현상
Index Sparse : 인덱스 전반적으로 밀도가 떨어지는 현상
비트맵 인덱스
Grant Select, Update on tbl to User
업데이트는 select와 update 둘다 권한 줘야함.
With Grant Option 주면 대상이 권한을 줄 수 있는 권한이 생김
단일컬럼 인덱스에서 Null 저장안함. 검색불가
결합 인덱스에서 null 검색시 둘다 null허용이면 불가능.
만약 위에서 부서번호가 Not null이면 3번 쿼리도 가능.
조건절에서 문자형 컬럼에 숫자 대입하면 안됨
where To_number(컬럼) = 100 인덱스 사용 불가
조건절에서 숫자형 컬럼에 LIKE 사용하면 안됨
where To_Char(계좌번호) LIKE :no || '%'
조건절에 or 로 인덱스를 사용하려면 or 양쪽 둘다 인덱스 range scan이 가능해야함. 아니면 Use_concat 사용하여 UNION ALL로 분기하지 않는다.
선분이력에서 최근 시점을 주로 조회 : 종료일자를 선두로 검색
선분이력에서 과거 시점을 주로 조회 : 시작일자를 선두로 검색
해시조인은 =조건이 많을수록 해시 맵을 세밀하게 구성하여 충돌률을 낮춘다.
스칼라 서브쿼리는 반드시 캐시 영향을 고려하여 사용
필수/옵션 관계의 구조일때 스칼라 -> 일반 조인시 Outer 조인 고려해야함
1:M M:1 구조일때 일반조인 -> 스칼라시 집계함수 / Rownum <=1 고려해야함
~~개 상품/ 주문 등을 고르게 입력한다 or 주문한다 -> 해시 조인시 충돌 낮음 암시하므로 해시조인 검토
규칙기반 옵티마이저는 통계정보 전혀 활용 x
바인드 변수는 최적화 과정에 컬럼 히스토그램 사용 못하므로 상수값을 사용할 때보다 안좋은 실행계획을 세울 가능성이 있음
라이브러리 캐시: SQL문을 캐싱하여 같은 실행계획을 바로 사용함
세선 켜서 캐싱 : SQL문과 공유커서를 가르키는 포인터 저장
애플리케이션 커서 캐싱 : 라이브러리에서 SQL을 찾는 과정을 생략하고 바로 반복적 수행. (Parse != Execute)
파티셔닝 된 테이블 풀스캔 하면 조건절에 알맞게 스캔함.
Index FFS : 세그먼트 전체를 스캔, 순서 보장x, MultiBlock IO, 병렬스캔 가능, 인덱스에 포함된 컬럼만 조회 가능
인라인뷰가 있는데도 실행계획에 VIEW가 없다면 뷰머징이 발생한 것.
내장 함수
함수 | 내용 |
---|---|
LOWER | 소문자로 변환 |
UPPER | 대문자로 변환 |
CONCAT | 문자 결합 |
SUBSTR | 문자 자르기 |
LENGTH, LEN | 문자 길이 |
LTRIM, TRIM, RTRIM | 소문자로 변환 |
ASCII | 문자 -> ASCII코드 |
CHR | ASCII코드 -> 문자 |
LPAD, RPAD | (값, 총길이, 채움문자) |
----------------------------------------- | ----------------- |
ABS | 절대값 |
SIGN | 음수,양수,0 판별 |
MOD | (A,B) A%B |
CEIL | 큰 정수 리턴 |
FLOOR | 작은 정수 리턴 |
ROUND | 반올림, 소수점자리 지정 |
TRUNC | 소수점 버림, 자리지정 |
----------------------------------------- | ---------------- |
SYSDATE | 오늘날짜 시간 |
EXTRACT('YEAR', 'MONTH', 'DAY' FROM DATE) | 날짜 추출 |
TO_CHAR(DATE,'YYYY') | 날짜 추출 |
TO_NUMBER | 숫자로 변환 |
TO_DATE0 | 날짜로 변환 |
분석 함수
함수 | 내용 |
---|---|
RATIO_TO_REPORT (백분율을 소수점) | 0.22 0.29 0.22 0.27 |
PERCENT_RANK (순서별 백분율) | 0.00 0.50 1.00 |
CUME_DIST (누적 백분율) | 0.33 0.67 1.00 |
NTILE (4) (테이블을 4등분으로 나누고 각 구역에 순서를 매김) |
조건 | 쿼리 |
---|---|
루트의 조건 | start with mgr is null and sal > 3000 connect by prior empno = mgr |
계층의 조건 | start with mgr is null connect by prior empno = mgr and sal > 3000 자식의 급여 3000이상 ----------------------------------------- start with mgr is null connect by prior empno = mgr and prior sal > 3000 부모의 급여 3000이상. ----------------------------------------- |
결과의 조건 | where sal > 3000 start with mgr is null connect by prior empno = mgr |
힌트 | 내용 |
---|---|
ALL_ROWS | 모든 로우를 출력하는것을 목표로 실행계획 수립 |
FIRST_ROWS | 조건에 맞는 첫번째 row를 리턴하는 실행계획 수립 |
FULL(table) | table FullScan |
HASH(table) | Hash Scan |
INDEX(table index) | Index Scan |
INDEX_DESC(table, index) | 해당 테이블 특정 인덱스로 내림차순 스캔 |
INDEX_FFS(table, index) | 인덱스 Fast Full Scan |
ORDERED | From 절에 기술된 순서대로 Join 진행 |
Leading(table1, table2 . .) | 기술한 순서대로 조인 진행 |
USE_NL, USE_HASH, USE_MERGE | 조인 방식 |
Unnest | 서브쿼리를 풀어내어 조인 |
No_Unnest | 서브쿼리를 풀어내지 않고 실행 |
HASH_AJ, NL_AJ, MERGE_AJ | 안티 조인 (Not Exists) |
HASH_SJ, NL_SJ, MERGE_SJ | 세미 조인 (Exists) |
push_subq | 서브쿼리를 먼저 실행 (항상 No_Unnest) |
no_push_subq | 서브쿼리 push를 방지 |
merge | 뷰 머징 실행 |
no_merge | 뷰 머징 방지 |
push_pred(table) | 조인 조건 PushDown (항상 no_merge, use_nl) |
no_push_pred(table) | 조인 조건 PushDown 방지 |
swap_join_inputs(table) | Hash Join에서 Build Table 지정 |
no_swap_join_inputs(table) | Hash Join에서 Build Table 지정 안함 |
append | direct Path Insert를 활용하여 버퍼캐시를 거치지않아서 빠름 |
alter table table_name nologging; | 로그 남기지 않게 설정 |
alter session enable parallel dml; | 대량 인서트시 병렬로 가능 |
NOPARALLEL(table) | Parallel Query 방지 |
PARALLEL(table, degree) | Parallel Query 실행, process 갯수 지정 |
PARALLEL_Index(table, index) | 병렬로 인덱스 스캔 |
use_concat | OR_Expansion 지정 실행 계획에는 CONCATENATION 출력 |
No_Expand | OR_Expansion 지정 안함 |
qb_name(subq) | 메인쿼리에서 사용할 수 있도록 서브쿼리의 이름 지정 사용시엔 unnest(@subq) / leading(거래@subq) 로 사용 |
pq_distribute | (inner집합, outer집합 분배방식, inner 집합 분배방식) |
Materialize | WITH 문으로 정의한 집합을 물리적으로 생성하도록 유도 WITH /*+Materialize*/ T AS (select-- |
Inline | WITH 문으로 정의한 집합을 물리적으로 생성하지 않고 Inline으로 처리하도록 유도 |
No_NLJ_Batching | 배치 NL 조인 방지 |
FORCE ORDER | SQL Server에서 Ordered의 역할 |
Hash, Sort Group | Group by 수단 지정 |
LOOP JOIN | NL 조인 |
from emp with (forceScan) | Fullscan |
from emp with (forceSeek) | 인덱스 스캔 |
Select 절을 분석하여 불필요한 조인이 있는지 검토 필수, 튜닝 중 제일 먼저 분석하길
스칼라 서브쿼리, 중첩 서브쿼리 등 일때 1:M인지 체크할것, 1:M이라면 에러나므로 rownum을 하던지 그룹화 하던지해서 1:1로 맞춰야함
소트 연산 생략은 곧 부분 범위 처리와 같다. 소트 생략의 목적이 전부다 읽고 소트가 아닌 필요한 부분만 읽을려고 하는것이다.
곧 소트연산 생략 = 부분 범위 처리 = NL 조인
실행계획의 블록, 로우 출력값을 보고 어떤 조인이 필요없는지 병목구간 어딘지 체크
스칼라를 쓸때는 무조건 입력값의 범위를 보고 캐싱효과가 있을지 체크
스칼라는 PGA에 캐싱됨