📝Single Block I/O
DB에서 데이터들은 일반적으로 HDD에 저장되는데 레코드를 한번의 I/O Call에 한줄(하나의 데이터 블록)씩 읽어오는 걸 의미한다.
인덱스를 이용한 실행계획일 때 Single Block I/O 방식으로 이용하게 된다.
그 이유는 인덱스는 블록간 논리적 순서는 물리적으로 데이터파일에 저장된 순서가 달라 그 블록들이 논리적 순서로는 한참 뒤쪽에 위치할 수 있습니다.
소량데이터를 읽을때 주로 사용하는 방식입니다.
📝Multi Block I/O
DB에서 데이터들은 일반적으로 HDD에 저장되는데 I/O Call 시점에 인접한 블록들을 같이 읽어 메모리에 적재하는 것을 의미합니다.
테이블 전체를 스캔할때 이 방식을 사용하며 테이블이 클수록 Multiblock I/O 단위도 크면 좋고 많은 데이터 블록을 읽을때 주로 사용합니다.
하지만 OS가 일반적으로 허용하는 I/O 단위가 1MB이면 1MB만큼만 읽습니다.
db file sequential read : Single Block I/O방식으로 I/O요청할때 발생
db file scattered read : Multiblock I/O 방식으로 I/O요청할때 발생
대량의 데이터를 Multiblock I/O방식으로 읽을 때 Single Block I/O보다 성능상 유리한 것은 I/O Call 발생횟수를 줄여주기 때문입니다.
📝바인드 변수
고정적인 쿼리문이 있을 뿐더러 동적으로 쿼리문이 들어가는 경우도 존재합니다.
이렇게 ?와 같이 동적으로 변하는 부분의 변수는 바인드 변수라고 합니다.
예) select * from tab where id = ?
해당 변수의 목적은 Hard Parse 를 줄이기에 있습니다.
바인드 변수를 사용할 경우 변수의 값이 달라져도 같은 문장으로 인식하기 때문에 불필요한 Hard Parse를 줄일 수 있습니다.
SQL 문의 경우 Hard parsing 이 많아지면 자원소모가 많아지며 실행이 느려지게 됩니다.
자바로 설명하겠습니다.
Connection con = null;
String query = "select * from shop where id = " + id;
Statement stmt = con.createStatement(stmt);
ResultSet rs = stmt.executeQuery();
이런식으로 코딩하게 될 경우 아래와 같이 쿼리문이 들어가게 됩니다.
select * from shop where id = 1;
select * from shop where id = 2;
select * from shop where id = 3;
다른 문장으로 처리가 되기 때문에 Hard Parse를 하게 되어 느려지게 됩니다.
하지만 아래와 같이 바인드변수를 이용할 경우 모두 같은 실행 계획을 세우게 되고 Soft Parse가 되기 때문에 실행계획을 안 세워서 빠르게 결과를 받을 수 있습니다.
select * from shop where id = ?
아래와 같은 방식으로 처리할 경우 바인드 변수 처리가 되지 않습니다.
String query = "select * from shop where id = " + id;
PreparedStatement pstmt = con.prepareStatement(query);
아래와 같은 형식으로 처리해야 바인드변수 처리가 됩니다. 고로 바인드 변수는 무조건 이용하되 라이브러리가 지원해주는 형식으로 사용하는 방법을 찾아서 써야합니다.
String query = "select * from shop where id = ?"
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setInt(1, id);
Parse해 실행계획을 처리할 경우 CPU 점유율 차이가 20%나 차이가 난다고 합니다.
또한 바인드 변수 사용할 때 해당 바인드 변수를 이용하는 조건절따위에 인덱스가 걸려있어도 형변환으로 인해 인덱스를 안 탈 수도 있기 때문에 주의해야한다.
📝SQL 실행 순서
SQL을 입력 받을시 제일 먼저 실행하려고 문법 오류를 검사한다.
그 후 SQL 이전 실행한 적 있는지 메모리(SHARED POOL)를 검사한다 있다면 기존에 실행한 방식으로 실행한다 이것을 SOFT PARSING이라고 한다.
하지만 그와 같은 기록이 없다면 SQL을 어떤 방식으로 처리할 것인지 실행 계획을 세운다. 이것을 HARD PARSING이라고 한다. 그 이후에 SHARED POOL에 실행 게획을 저장한다.
📝SQL 동작방식
Soft Parse : Parsing → syntax → semantic → Execution
Hard Parse : Parsing → syntax → semantic → Query Transformer → Estimator → Plan Generator → Execution
Query Transformer
PARSING 과정을 거친 SQL은 PARSING 트리 형태로 변형되어 Query Transformer는 넘겨 받은 SQL을 보고 같은 결과를 도출하되 좀 더 나은 실행 계획을 갖는 SQL로 변형이 가능한지 판단해 변환 작업을 수행
예를 들면 복잡한 서브쿼리나 뷰를 사용한 SQL을 일반적인 조인 형태의 SQL로 변환해 실행 계획을 도출하기 좋은 상태로 만든다.
Estimator
Query Transformer를 통해 변환 작업을 마치고난 SQL은 Estimator로 넘겨지게 되는데 이때 수행하는데 드는 총 비용을 계산한다.
Plan Generator
Estimator를 통해 계산된 값들을 토대로 후보군 실행계획 도출 Row Source Generator를 통해 출력이 가능한 코드 형태로 바꾼다.
📝실행시간 (Execution time) vs 패치시간 (Fetch time)
실행 시간은 SQL문을 Parse해 실행 계획을 세워 실행하는데까지 걸리는 시간이다.
패치 시간은 실행해서 나온 결과를 전송하는 데 걸리는 시간을 측정한다 (Binary로 전달하기 때문에 네트워크 연결에 의존한다)
🔗 참고 및 출처
https://blogingming.tistory.com/entry/%EC%8B%A4%ED%96%89%EC%8B%9C%EA%B0%84-Execution-time-vs-%ED%8C%A8%EC%B9%98%EC%8B%9C%EA%B0%84-Fetch-time
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gh2501&logNo=115281737
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gh2501&logNo=115281737
https://sksstar.tistory.com/89
http://wiki.gurubee.net/display/STUDY/03.+Single+Block+vs+Multiblock+IO
https://argolee.tistory.com/60