{*}커서(Cursor)*
상황에 따라 여러 가지 의미로 사용되고 있으며
하나의 의미로 표현되지 않고 아래에서 설명하고 있는 3종류의 커서를 일컫는 말
Cursor c = new Cursor();
오라클에서 "커서를 공유한다"는 표현은 라이브러리 캐시의 공유 커서(shared cursor)를 말함.
라이브러리 캐시에 공유돼 있는 커서의 수행 통계를 v$sql을 통해 조회 가능
SCOTT@orcl > ALTER SYSTEM FLUSH SHARED_POOL;
시스템이 변경되었습니다.
SCOTT@orcl > select /* cursor_test */*
2 from emp
3 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select sql_id , parse_calls, loads, executions, invalidations,
2 decode(sign(invalidations), 1, (loads-invalidations), 0) reloads
3 from v$sql
4 where sql_text like '%/* cursor_test */%'
5 and sql_text not like '%v$sql%';
SQL_ID PARSE_CALLS LOADS EXECUTIONS INVALIDATIONS RELOADS
------------- ----------- ---------- ---------- ------------- ----------
3fu5pr5zu4t1h 1 1 1 0 0
parse_calls | 라이브러리 캐시에서 SQL 커서를 찾으려고 요청한 횟수. |
---|---|
loads | 하드파싱을 거친 SQL 실행계획을 라이브러리 캐시에 적재한 횟수. |
executions | SQL을 수행한 횟수. |
invalidations | 커서가 무효화된 횟수. 커서가 참조하고 있는 오브젝트에 중요한 변화가 일어났음을 의미함. |
SCOTT@orcl > select /* cursor_test */*
2 from emp
3 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select /* cursor_test */*
2 from emp
3 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select /* cursor_test */*
2 from emp
3 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select sql_id , parse_calls, loads, executions, invalidations,
2 decode(sign(invalidations), 1, (loads-invalidations), 0) reloads
3 from v$sql
4 where sql_text like '%/* cursor_test */%'
5 and sql_text not like '%v$sql%'
6 ;
SQL_ID PARSE_CALLS LOADS EXECUTIONS INVALIDATIONS RELOADS
------------- ----------- ---------- ---------- ------------- ----------
3fu5pr5zu4t1h 4 1 4 0 0
SCOTT@orcl > disconnect
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options에서 분리되었습니다.
@ > conn scott/tiger
연결되었습니다.
SCOTT@orcl >
SCOTT@orcl > select /* cursor_test */*
2 from emp
3 where empno ='7788'
4 ;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select sql_id , parse_calls, loads, executions, invalidations,
2 decode(sign(invalidations), 1, (loads-invalidations), 0) reloads
3 from v$sql
4 where sql_text like '%/* cursor_test */%'
5 and sql_text not like '%v$sql%';
SQL_ID PARSE_CALLS LOADS EXECUTIONS INVALIDATIONS RELOADS
------------- ----------- ---------- ---------- ------------- ----------
3fu5pr5zu4t1h 5 1 5 0 0
//;을 붙여서 실행을 하게 되면 동일하지 않은 쿼리로 분석을 하게 된다.
SCOTT@orcl > select /* cursor_test */*
2 from emp
3 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select sql_id , parse_calls, loads, executions, invalidations,
2 decode(sign(invalidations), 1, (loads-invalidations), 0) reloads
3 from v$sql
4 where sql_text like '%/* cursor_test */%'
5 and sql_text not like '%v$sql%';
SQL_ID PARSE_CALLS LOADS EXECUTIONS INVALIDATIONS RELOADS
------------- ----------- ---------- ---------- ------------- ----------
3fu5pr5zu4t1h 5 1 5 0 0
1qnr0wvwvv2wk 1 1 1 0 0
SCOTT@orcl > BEGIN
2 DBMS_STATS.GATHER_TABLE_STATS
3 ( ownname => USER
4 , tabname => 'EMP'
5 , no_invalidate => FALSE
6 );
7 END;
8 /
PL/SQL 처리가 정상적으로 완료되었습니다.
SCOTT@orcl > select /* cursor_test */*
2 from emp
3 where empno ='7788'
4 ;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select sql_id , parse_calls, loads, executions, invalidations,
2 decode(sign(invalidations), 1, (loads-invalidations), 0) reloads
3 from v$sql
4 where sql_text like '%/* cursor_test */%'
5 and sql_text not like '%v$sql%';
SQL_ID PARSE_CALLS LOADS EXECUTIONS INVALIDATIONS RELOADS
------------- ----------- ---------- ---------- ------------- ----------
3fu5pr5zu4t1h 1 2 1 1 1
{*}Child 커서란?*
SQL문장이 100% 동일한대도 동일쿼리를 실행하는 사용자 스키마가 다르다면 각각의 다른 테이블을 액세스하게 되며 실행계획 또한 달라진다.
이럴 때 오라클은 하나의 Parent커서에 여러개의 Child 커서를 가지게 된다.
SCOTT@orcl > conn sys/manager as sysdba;
연결되었습니다.
SYS@orcl AS SYSDBA> select /* cursor_test */* from emp
2 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SYS@orcl AS SYSDBA> select sql_id , version_count, optimizer_mode, address, hash_value
2 from v$sqlarea
3 where sql_text like '%/* cursor_test */%'
4 and sql_text not like '%v$sql%' ;
SQL_ID VERSION_COUNT OPTIMIZER_ ADDRESS HASH_VALUE
------------- ------------- ---------- -------- ----------
1auaf2z18m8ks 1 ALL_ROWS 2E734D4C 3263799896
SYS@orcl AS SYSDBA> select sql_id , child_number, optimizer_mode, address, hash_value
2 from v$sql
3 where sql_text like '%/* cursor_test */%'
4 and sql_text not like '%v$sql%';
SQL_ID CHILD_NUMBER OPTIMIZER_ ADDRESS HASH_VALUE
------------- ------------ ---------- -------- ----------
1auaf2z18m8ks 0 ALL_ROWS 2E734D4C 3263799896
--다시 다른 계정으로 들어가서 테이블 같이 쿼리 실행
SCOTT@orcl > select /* cursor_test */* from emp
2 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select sql_id , version_count, optimizer_mode, address, hash_value
2 from v$sqlarea
3 where sql_text like '%/* cursor_test */%'
4 and sql_text not like '%v$sql%' ;
SQL_ID VERSION_COUNT OPTIMIZER_ ADDRESS HASH_VALUE
------------- ------------- ---------- -------- ----------
1auaf2z18m8ks 2 ALL_ROWS 2E734D4C 3263799896
1auaf2z18m8ks 2 ALL_ROWS 2E734D4C 3263799896
SCOTT@orcl > select sql_id , child_number, optimizer_mode, address, hash_value
2 from v$sql
3 where sql_text like '%/* cursor_test */%'
4 and sql_text not like '%v$sql%';
SQL_ID CHILD_NUMBER OPTIMIZER_ ADDRESS HASH_VALUE
------------- ------------ ---------- -------- ----------
1auaf2z18m8ks 0 ALL_ROWS 2E734D4C 3263799896
1auaf2z18m8ks 1 ALL_ROWS 2E734D4C 3263799896
SCOTT@orcl > ALTER SESSION SET OPTIMIZER_MODE='ALL_ROWS';
세션이 변경되었습니다.
SCOTT@orcl > select /* cursor_test */* from emp
2 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > ALTER SESSION SET OPTIMIZER_MODE='FIRST_ROWS';
세션이 변경되었습니다.
SCOTT@orcl > select /* cursor_test */* from emp
2 where empno ='7788';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87/04/19 3000 20
SCOTT@orcl > select sql_id , version_count, optimizer_mode, address, hash_value
2 from v$sqlarea
3 where sql_text like '%/* cursor_test */%'
4 and sql_text not like '%v$sql%' ;
SQL_ID VERSION_COUNT OPTIMIZER_ ADDRESS HASH_VALUE
------------- ------------- ---------- -------- ----------
1auaf2z18m8ks 3 ALL_ROWS 2E734D4C 3263799896
1auaf2z18m8ks 3 FIRST_ROWS 2E734D4C 3263799896
SCOTT@orcl > select sql_id , child_number, optimizer_mode, address, hash_value,
parsing_user_id
2 from v$sql
3 where sql_text like '%/* cursor_test */%'
4 and sql_text not like '%v$sql%';
SQL_ID CHILD_NUMBER OPTIMIZER_ ADDRESS HASH_VALUE PARSING_USER_ID
------------- ------------ ---------- -------- ---------- ---------------
1auaf2z18m8ks 0 ALL_ROWS 2E734D4C 3263799896 0
1auaf2z18m8ks 1 ALL_ROWS 2E734D4C 3263799896 54
1auaf2z18m8ks 2 FIRST_ROWS 2E734D4C 3263799896 54
SCOTT@orcl > select child_number, child_address, optimizer_mode_mismatch, optimizer_mismatch
2 from v$sql_shared_cursor
3 where sql_id ='1auaf2z18m8ks'
4 and address ='2E734D4C';
CHILD_NUMBER CHILD_AD O O
------------ -------- - -
0 2CA5CF88 N N
1 2E72158C N N
2 2E5B62EC Y N
SCOTT@orcl > DECLARE
2 l_cnt NUMBER;
3 l_child_cnt NUMBER;
4 l_prev_child_cnt NUMBER;
5 l_bind_value VARCHAR2(4000);
6 l_sql_id VARCHAR2(13);
7 BEGIN
8 l_prev_child_cnt := 0;
9
10 FOR c IN 1..4000 LOOP
11 l_bind_value := LPAD('A', c, '0');
12
13 SELECT COUNT(*)
14 INTO l_cnt
15 FROM T
16 WHERE C = l_bind_value;
17
18
19 IF c = 1 THEN
20 SELECT PREV_SQL_ID
21 INTO l_sql_id
22 FROM V$SESSION
23 WHERE SID = USERENV('SID')
24 AND USERNAME IS NOT NULL
25 AND PREV_HASH_VALUE <> 0;
26
27 DBMS_OUTPUT.PUT_LINE('SQL_ID --> ' || l_sql_id);
28 END IF;
29
30 SELECT COUNT(*)
31 INTO l_child_cnt
32 FROM V$SQL
33 WHERE SQL_ID = l_sql_id;
34
35 IF l_prev_child_cnt < l_child_cnt THEN
36 DBMS_OUTPUT.PUT_LINE(c);
37
38 l_prev_child_cnt := l_child_cnt;
39 END IF;
40 END LOOP;
41 END;
42 /
SQL_ID --> f6qwn8zavty07
l
33
129
2001
PL/SQL 처리가 정상적으로 완료되었습니다.
SCOTT@orcl > SELECT CHILD_NUMBER,
2 BIND_MISMATCH
3 FROM V$SQL_SHARED_CURSOR
4 WHERE SQL_ID = 'f6qwn8zavty07'
5 ORDER BY CHILD_NUMBER
6 ;
CHILD_NUMBER B
------------ -
0 N
1 Y
2 Y
3 Y
SELECT * FROM CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT * FROM Customer;
SELECT * FROM CUSTOMER;
SELECT * FROM HR.CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT /*주석*/* FROM CUSTOMER;
SELECT * FROM CUSTOMER;
SELECT /*+ all_rows */* FROM CUSTOMER;
SELECT * FROM CUSTOMER WHERE CUST_ID = '000001';
SELECT * FROM CUSTOMER WHERE CUST_ID = '000002';