Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=209 Card=5 Bytes=175)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (Cost=2 Card=5 Bytes=85)
2 1 NESTED LOOPS (Cost=209 Card=5 Bytes=175)
3 2 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (Cost=207 Card=1 Bytes=18)
4 3 INDEX (RANGE SCAN) OF 'DEPT_LOC_IDX'(NON-UNIQUE) (Cost=7 Card=1)
5 2 INDEX (RANGE SCAN) OF 'EMP_DEPTNO_IDX'(NON-UNIQUE) (Cost=1 Card=5)
파싱종류 | 설명 |
---|---|
소프트파싱 (Soft Parsing) | SQL과 실행계획을 캐시에서 찾아 곧바로 실행단계로 넘어가는 경우 |
하드파싱(Hard Parsing) | SQL과 실행계획을 캐시에서 찾지 못해 최적화 과정을 거치고 나서 실행단계로 넘어가는 경우 |
중요
SELECT * FROM CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT * FROM Customer;
SELECT * FROM CUSTOMER;
SELECT /* 주석문 */ * FROM CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT * FROM HR.CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT /*+ all_rows */ * FROM CUSTOMER;
SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'tommy';
SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'karajan';
SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'javaking';
SELECT * FROM CUSTOMER WHERE LOGIN_ID = 'oraking';
procedure LOGIN_TOMMY() { ... }
procedure LOGIN_KARAJAN() { ... }
procedure LOGIN_JAVAKING() { ... }
procedure LOGIN_ORAKING() { ... }
.
.
.
procedure LOGIN(login_id in varchar2) { ... }
SELECT * FROM CUSTOMER WHERE LOGIN_ID = :LOGIN_ID;
ORACLE | SQL Server |
---|---|
cursor_sharing 파라미터 force 또는 similar 설정 | 단순매개 변수화 활성화(default) |
오라클 | SQL Server |
---|---|
바인드 변수 Peeking | Parameter Sniffing |
Proc*C 구분으로 Static SQL 작성한 예시
int main()
{
printf("사번을 입력하십시오 : ");
scanf("%d", &empno);
EXEC SQL WHENEVER NOT FOUND GOTO notfound;
EXEC SQL SELECT ENAME INTO :ename
FROM EMP
WHERE EMPNO = :empno;
printf("사원명 : %s.\n", ename);
notfound:
printf("%d는 존재하지 않는 사번입니다. \n", empno); }
int main()
{
char select_stmt[50] = "SELECT ENAME FROM EMP WHERE EMPNO = :empno";
// scanf("%c", &select_stmt); → SQL문을 동적으로 입력 받을 수도 있음
EXEC SQL PREPARE sql_stmt FROM :select_stmt;
EXEC SQL DECLARE emp_cursor CURSOR FOR sql_stmt;
EXEC SQL OPEN emp_cursor USING :empno;
EXEC SQL FETCH emp_cursor INTO :ename;
EXEC SQL CLOSE emp_cursor;
printf("사원명 : %s.\n", ename);
}
for(;;) {
EXEC ORACLE OPTION (HOLD_CURSOR=YES);
EXEC ORACLE OPTION (RELEASE_CURSOR=NO);
EXEC SQL INSERT ...... ; // SQL 수행
EXEC ORACLE OPTION (RELEASE_CURSOR=YES);
}
call count cpu elapsed disk query current rows
----- ------ ----- ------- ----- ------- ------ -----
Parse 1 0.00 0.00 0 0 0 0
Execute 5000 0.18 0.14 0 0 0 0
Fetch 5000 0.17 0.23 0 10000 0 5000
----- ------ ----- ------- ----- ------- ------ -----
total 10001 0.35 0.37 0 10000 0 5000
Misses in library cache during parse: 1
public static void CursorCaching(Connection conn, int count) throws Exception{
// 캐시 사이즈를 1로 지정
((OracleConnection)conn).setStatementCacheSize(1);
// 묵시적 캐싱 기능을 활성화 ((OracleConnection)conn).setImplicitCachingEnabled(true);
for (int i = 1; i <= count; i++) {
// PreparedStatement를 루프문 안쪽에 선언
PreparedStatement stmt = conn.prepareStatement(
"SELECT ?,?,?,a.* FROM emp a WHERE a.ename LIKE 'W%'"); stmt.setInt(1,i);
stmt.setInt(2,i); stmt.setString(3,"test");
ResultSet rs=stmt.executeQuery();
rs.close();
// 커서를 닫더라도 묵시적 캐싱 기능을 활성화 했으므로 닫지 않고 캐시에 보관하게 됨
stmt.close();
}
}
public static void CursorHolding(Connection conn, int count) throws Exception{
// PreparedStatement를 루프문 바깥에 선언
PreparedStatement stmt = conn.prepareStatement(
"SELECT ?,?,?,a.* FROM emp a WHERE a.ename LIKE 'W%'");
ResultSet rs;
for (int i = 1; i <= count; i++) {
stmt.setInt(1,i);
stmt.setInt(2,i);
stmt.setString(3,"test");
rs=stmt.executeQuery();
rs.close();
} // 루프를 빠져 나왔을 때 커서를 닫는다.
stmt.close();
}
- 강좌 URL : http://www.gurubee.net/lecture/2392
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.