글
select rownum, <-- selete 절은 내게 리턴할 결과 값의 형태(templet)에 대해 내가 지정할수 있는 구문.
mod(rownum, 1000), <-- 1000으로 나눈 나머지
floor((rownum-1)/1000), <-- 소숫점 버리기: 로직이 멋짐.. 예전 floor 할때 + 좌로 시프트하고 + 0.5 한후에
lpad('x', 1000, 'x') <-- LPAD 함수설명 LPAD함수는 문자열이 일정 길이(byte)가 될 때까지 왼쪽에 특정 문자를 덧붙인다.
from <-- from 절이 실제로 파일의 물리적 주소에 접근할 위치 지정
all_source a1, all_source a2
where rownum <= 1e6; <-- 물리적 주소에 접근해서 메모리(selete절)로 읽어들일지 말지의 조건문이지만
의문점이. 데이터에 대한 조회 업무 외의 작업인.. 데이터 가공 to_char(format) to_date(format)
FROM hr.employees e, hr.departments d
WHERE d.department_name IN ('Marketing', 'Sales')
AND e.department_id = d.department_id;
이 쿼리의 플랜은
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 19 | 722 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | | | | |
| 2 | NESTED LOOPS | | 19 | 722 | 3 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL | DEPARTMENTS | 2 | 32 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 10 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 10 | 220 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("D"."DEPARTMENT_NAME"='Marketing' OR "D"."DEPARTMENT_NAME"='Sales')
4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
보통 매우 큰 인덱스를 Range/Full/Skip scan을 한 후 테이블 Access를 수항하면, 엄청난 양의 Single Block Read가 발생합니다.
클러스터링 Fact에 따라, Index Leaf Block 의 Rowid 갯수에 따라 Table lookup 발생하면서 Table Block Read가 발생합니다. (내 예측이 맞았는듯.. 인덱스는 이진 트리로 구성하고..거기에 실제 파일 데이터를 연결 리스트or 리스트
형식으로 배치한듯..)
순차적 수행 플랜의 경우, 쿼리 성능은 Single Random table Read가 얼마나 빠른가에 좌우 되었습니다.
만약 단일 블록 하나를 읽는데 5ms 이 필요하다면, 1000 block을 읽는데 약 5초 정도가 소요됩니다.
다만 여기에서도 스토리지 시스템이 동시 IO 요청을 처리할 수 있으며, 최종 사용자 세션이 필요한 블록을 동시에 수행하는 어떤 방법이나, 병렬로 처리할 수 잇따면,
OS와 스토리지와의 연결 상에서 부하가 될 수 있겠지만 사용자는 더 짧은 시간에 결과를 받아 볼 수 있습니다.
오라클은 어떻게 IO를 최적화했는가?
현재까지 제가 아는 한, 오라클은 12.1 버전 이전에서도 몇가지 교묘한 방법으로 IO를 다루어 왔습니다. 아래는 그 몇몇가지 방법입니다.
- Nested Loop Join 에해서 오라클에 사용자에 대한 몇가지 전략이 사용됨 : NL-Join Batching 과 Table Access를 Join 밖으로 이동시켰습니다.
--NL-JOIN Batching (http://docs.oracle.com/cd/E11882_01/server.112/e41573/optimops.htm#PFGRF94642)
11g에서는 Physical IO의 지연을 감소시키기 위하여 NL Join 에 대한 새로운 방식을 소개합니다.
Table Block 이나, index Block이 Buffer Cache에 존재하지 않지만, Join 에 필요한 경우 Physical IO가 필요합니다.
오라클 데이터베이스 11g는 한번에 하나씩 처리하는 대신 여러 Physical IO 요청을 묶어 Vector IO를 사용하여 처리할 수 있습니다.
이전 버전의 Exeution Plan에서 한 line으로 나타났던 Nested Loop Join의 Row source가 두번의 Nested Loop Join Row source로 나타나게 되었습니다.
이 경우, Oracle 데이터베이스는 첫번째 NL Join Row source를 Inner 쪽 인덱스와 Outer 쪽 Table에 Join 으로 할당합니다.
두번째 Row Source는 index에 저장된 Rowid를 포함한 첫번째 join 결과 set과 Inner 쪽 Table사이의 Join 에 할당합니다.
즉,
SELECT e.first_name, e.last_name, e.salary, d.department_name
FROM hr.employees e, hr.departments d
WHERE d.department_name IN ('Marketing', 'Sales') <-어제 봤던 부분.. IN(a or b)키워드= 풀스캔..
AND e.department_id = d.department_id;
이 쿼리의 플랜은
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 19 | 722 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | | | | |
| 2 | NESTED LOOPS | | 19 | 722 | 3 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL | DEPARTMENTS | 2 | 32 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 10 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 10 | 220 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("D"."DEPARTMENT_NAME"='Marketing' OR "D"."DEPARTMENT_NAME"='Sales')
4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
로 수행됩니다.
첫 번째 Join 의 결과집합은 다시 두번 째 Join 의 Outer Side가 되며, Hr.Employee Table은 Inner Side가 됩니다.
이전 버전의 실행계획과 동일하게 표시되는, 두번째 Join row source가 할당되지 않는 경우는 다음과 같습니다.
- Inner Side에서 필요한 모든 컬럼이 Index 상에 있어 Table Access가 필요없는 경우. 이 경우, Oracle은 오직 한번만 Join 한다 <--이게 핵심인듯하다. 조인을 위해 첫번째 선택해주는 인덱스에 대해 loop를 돌 필요가 없다면..
기존의 NL Join 방식을 사용할 수 있다.
- OPIMIZER_FEATURES_ENABLE 초기 파라메터가 11g 이전 버전으로 set 되어 있는 경우, 기존의 NL Join 을 수행한다.
http://prayyou.egloos.com/viewer/1799600
*******************************************************************
statement vs preparestatement
DiverManger.getConnection() 에서 하는 짓..
// Worker method called by the public getConnection() methods.
Connection con = aDriver.driver.connect(url, info);
'프로그래밍 > 데이터베이스' 카테고리의 다른 글
resultSet 에선 readObject가 안되다니 OTL (0) | 2014.01.02 |
---|---|
테이블간 조인 조건인 where 절에서 데이터 엑세스 조건 vs 처리(결과) 조건을 구분할 것! (0) | 2014.01.02 |
셀렉트문에서 -> 셀렉트 절에서 별칭의 의미 vs 프롬절에서 별칭의 의미 (0) | 2014.01.02 |
테이블 조인 연산시 쿼리에 따른 퍼포먼스(ms sql, 오라클 포럼 주소) (0) | 2014.01.02 |
관계형 db에서 관계(relation)의 개념 (추가ALTER TABLE .. 제약 조건 추가) 12/19 추가 (0) | 2014.01.01 |
RECENT COMMENT