8. 애플리케이션 커서 캐싱
2010.06.29 05:11
세션커서캐싱을 이용 하면 SGA이 공유 커서를 빠르게 찾아서 커서를 오픈 할 수 있다.
그렇다하더라도, 공유 커서 힙을 Pin 하고 실행에 필요한 메모리 공간을 PGA에 할당하는 등의 작업은 반복하게 한다.
애플리케이션 커서 캐싱을 이용하여 이 과정마저 생략하는 것이 가능하다.
- 패턴① : 바인드 변수를 사용하지 않을 때.
- 패턴② : 바인드 변수를 사용, 커서캐싱을 하지 않을 때.
- 패턴③ : 커서를 닫지 않고 재사용할 때.
- 패턴④ : 묵시적 캐싱 기능을 사용할 때.
각각의 패턴을 Java를 예로 살펴 보자.
패턴① 바인드 변수를 사용하지 않을 때.
/**
* 패턴1.
*/
public static void noBinding(Connection conn) throws Exception {
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = null;
for (int i = 1 ; i <= 5000; i++ ) {
sql = "SELECT /* no_biding */ " + i + "," + i + ",'test',a.* FROM scott.emp a WHERE a.ename LIKE 'W%'";
stmt = conn.prepareStatement(sql);
rs = stmt.executeQuery();
rs.close();
stmt.close();
}
}
위 소스를 보면 SQL문이 계속 변하는 것을 알 수 있다.
select /* no_binding */ 1,1,'test',a.* FROM scott.emp a WHERE a.ename LIKE 'W%'
select /* no_binding */ 2,2,'test',a.* FROM scott.emp a WHERE a.ename LIKE 'W%'
select /* no_binding */ 3,3,'test',a.* FROM scott.emp a WHERE a.ename LIKE 'W%'
.
.
.
select /* no_binding */ 5000,5000,'test',a.* FROM scott.emp a WHERE a.ename LIKE 'W%'
즉, 하드파싱이 대입값만큼 발생 (1~5000)
패턴② 바인드 변수를 사용、커서캐싱을 하지않을때.
/**
* 패턴2.
*/
public static void noCaching(Connection conn) throws Exception {
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = null;
for (int i = 1 ; i <= 5000; i++ ) {
sql = "SELECT /* no_biding */ ?,?,?,a.* FROM scott.emp a WHERE a.ename LIKE 'W%'";
stmt = conn.prepareStatement(sql);stmt.setInt(1, i);
stmt.setInt(2, i);
stmt.setString(3, "test");
rs = stmt.executeQuery();rs.close();
stmt.close(); // 커서를 닫음.
}
}
위 소스를 보면 SQL문은 한개로 해결. 바인드값만이 변함.
select /* no_binding */ ?,?,?,a.* FROM scott.emp a WHERE a.ename LIKE 'W%'
즉, 하드파싱이 한번만 일어난다.
그러나, 루프내에서 커서를 닫아, 항상 커서를 생성하게 된다.
- Parse Count : 5000
- Execute Count : 5000
- Fetch Count : 5000
패턴③ 커서를 닫지 않고 재사용할 경우.
/**
* 패턴3.
*/
public static void cursorHolding(Connection conn) throws Exception {
PreparedStatement stmt = null;
String sql = "SELECT /* no_biding */ ?,?,?,a.* FROM scott.emp a WHERE a.ename LIKE 'W%'";stmt = conn.prepareStatement(sql);
ResultSet rs = null;
for (int i = 1 ; i <= 5000; i++ ) {
stmt.setInt(1, i);stmt.setInt(2, i);
stmt.setString(3, "test");
rs = stmt.executeQuery();rs.close();
}
stmt.close(); // 루프가 끝나면 커서를 닫는다.}
위 소스를 보면 SQL문은 한개로 해결. 바인드값만이 변함.
select /* no_binding */ ?,?,?,a.* FROM scott.emp a WHERE a.ename LIKE 'W%'
즉, 하드파싱이 한번만 일어난다.
또한, 커서를 루프가 종료후에 닫고 있다. 이것을 애플리케이션 커서 라 한다.
- Parse Count : 1
- Execute Count : 5000
- Fetch Count : 5000
패턴④ 묵시적 캐싱을 사용할 경우.
/**
// 캐시 사이즈를 1로 지정
* 패턴4.
*/
public static void cursorCaching(Connection conn) throws Exception {((OracleConnection) conn).setStatementCacheSize(1);
// 묵시적 캐싱 기능을 활성화
((OracleConnection) conn).setImplicitCachingEnabled(true);
PreparedStatement stmt = null;
ResultSet rs = null;
for (int i = 1 ; i <= 5000; i++ ) {
String sql = "SELECT /* no_biding */ ?,?,?,a.* FROM scott.emp a WHERE a.ename LIKE 'W%'";stmt = conn.prepareStatement(sql);
stmt.setInt(1, i);
stmt.setInt(2, i);
stmt.setString(3, "test");
rs = stmt.executeQuery();
rs.close();
stmt.close(); // 루프가 끝나면 커서를 닫는다. 그러나, 내부적으로는 닫지않고 캐시에 보관
}
}
위 소스를 보면 패턴②와 같은 형태를 하면서도 사실상 패턴③과 같은 성능을 보인다.
즉, JDBC의 API에서 제공하는 기능을 이용하여 매번 커서를 닫는듯한 코딩을 해도 내부적으로는 세션커서캐싱을 한다.- Parse Count : 1
- Execute Count : 5000
- Fetch Count : 5000
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
» | 8. 애플리케이션 커서 캐싱 | 토시리 | 2010.06.29 | 6744 |
26 | 9. Static vs. Dynamic SQL [1] | balto | 2010.07.03 | 18612 |
25 | 10. Dynamic SQL 사용 기준 | balto | 2010.07.03 | 8763 |
24 |
11. Static SQL 구현을 위한 기법들
![]() | 실천하자 | 2010.07.04 | 12275 |
23 |
4. Array Processing 활용
![]() | 휘휘 | 2010.07.04 | 21045 |
22 | 1. Call 통계 | 실천하자 | 2010.07.04 | 10606 |
21 |
5. Fetch Call 최소화
![]() | 휘휘 | 2010.07.05 | 17115 |
20 | 5장. 데이터베이스 Call 최소화 원리 | 휘휘 | 2010.07.05 | 6245 |
19 |
2. User Call vs. Recursive Call
![]() | 토시리 | 2010.07.07 | 9195 |
18 |
3. 데이터베이스 Call이 성능에 미치는 영향
![]() | 토시리 | 2010.07.07 | 11808 |
17 | 6장. I/O 효율화 원리 | 휘휘 | 2010.07.07 | 6558 |
16 |
4. Prefetch
![]() | balto | 2010.07.10 | 28603 |
15 |
5. Direct Path I/O
![]() | balto | 2010.07.10 | 12357 |
14 | 8. PL/SQL 함수 호출 부하 해소 방안 | 토시리 | 2010.07.11 | 14227 |
13 | 6. 페이지 처리의 중요성 | 실천하자 | 2010.07.11 | 6975 |
12 | 2. Memory vs. Disk I/O | 휘휘 | 2010.07.11 | 7573 |
11 | 3. Single Block vs. Multiblock I/O | 휘휘 | 2010.07.11 | 9333 |
10 | 7. PL/SQL 함수의 특징과 성능 부하 | 실천하자 | 2010.07.12 | 12771 |
9 |
1. 블록 단위 I/O
![]() | 토시리 | 2010.07.12 | 9533 |
8 |
1. Library Cache Lock
![]() | balto | 2010.07.17 | 12950 |