8. 애플리케이션 커서 캐싱
2010.06.29 14: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
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
47 |
5. Fetch Call 최소화
![]() | 휘휘 | 2010.07.05 | 16851 |
46 | 1. Call 통계 | 실천하자 | 2010.07.05 | 10444 |
45 |
4. Array Processing 활용
![]() | 휘휘 | 2010.07.05 | 18250 |
44 |
11. Static SQL 구현을 위한 기법들
![]() | 실천하자 | 2010.07.05 | 12086 |
43 | 10. Dynamic SQL 사용 기준 | balto | 2010.07.04 | 8643 |
42 | 9. Static vs. Dynamic SQL [1] | balto | 2010.07.04 | 18347 |
» | 8. 애플리케이션 커서 캐싱 | 토시리 | 2010.06.29 | 6611 |
40 |
7. 세션 커서 캐싱
![]() | 토시리 | 2010.06.29 | 10620 |
39 |
6. 바인드 변수의 부작용과 해법
![]() | 실천하자 | 2010.06.28 | 14674 |
38 | 5. 바인드 변수의 중요성 | 실천하자 | 2010.06.28 | 11768 |
37 | 4장. 라이브러리 캐시 최적화 원리 | 휘휘 | 2010.06.28 | 6914 |
36 |
2. SQL 처리과정
![]() | 휘휘 | 2010.06.28 | 15670 |
35 |
1. SQL과 옵티마이저
![]() | 휘휘 | 2010.06.28 | 7218 |
34 |
4. 커서 공유
![]() | balto | 2010.06.28 | 9200 |
33 |
3. 라이브러리 캐시 구조
![]() | balto | 2010.06.28 | 9850 |
32 | 6. V$SYSTEM_EVENT | 토시리 | 2010.06.14 | 6523 |
31 | 10. V$SQL | 실천하자 | 2010.06.14 | 12680 |
30 |
5. V$SYSSTAT
[1] ![]() | 토시리 | 2010.06.14 | 9849 |
29 |
12. 데이터베이스 성능 고도화 정석 해법
![]() | 휘휘 | 2010.06.14 | 7153 |
28 | 11. End-To-End 성능관리 | 휘휘 | 2010.06.14 | 8095 |