Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 1 ■ DEVELOPING SUCCESSFUL ORACLE APPLICATIONS 43 ops$tkyte@ORA10G> select /* TAG */ substr( username, 1, 1 ) 2 from all_users au1 3 where rownum = 1; S - B ops$tkyte@ORA10G> alter session set cursor_sharing=force; Session altered. ops$tkyte@ORA10G> select /* TAG */ substr( username, 1, 1 ) 2 from all_users au2 3 where rownum = 1; SUBSTR(USERNAME,1,1) ------------------------------ B What happened there? Why is the column reported by SQL*Plus suddenly so large for the second query, which is arguably the same query? If we look at what the cursor sharing setting did for us, it (and something else) will become obvious: ops$tkyte@ORA10G> select sql_text from v$sql 2 where sql_text like 'select /* TAG */ %'; SQL_TEXT ------------------------------------------------------------------------------- select /* TAG */ substr( username, 1, 1 ) from all_users au1 where rownum = 1 select /* TAG */ substr( username, :"SYS_B_0", :"SYS_B_1" ) 2 where rownum = :"SYS_B_2" from all_users au The cursor sharing removed information from the query. It found every literal, including the parameters to the built-in substring function, which were constants we were using. It removed them from the query and replaced them with bind variables. The SQL engine no longer knows that the column is a substring of length 1—it is of indeterminate length. Also, you can see that where rownum = 1 is now bound as well. That seems like a good idea; however, the optimizer has just had some important information removed. It no longer knows that “this query will retrieve a single row”; it now believes “this query will return the first N rows and N could be any number at all.” In fact, if you run these queries with SQL_TRACE=TRUE, you will find the query plans used by each query and the amount of work they perform to be very different. Consider the following: select /* TAG */ substr( username, 1, 1 ) from all_users au1 where rownum = 1

44 CHAPTER 1 ■ DEVELOPING SUCCESSFUL ORACLE APPLICATIONS call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 77 0 1 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 4 0.00 0.00 0 77 0 1 Misses in library cache during parse: 0 Optimizer mode: ALL_ROWS Parsing user id: 412 Rows Row Source Operation ------- --------------------------------------------------- 1 COUNT STOPKEY (cr=77 pr=0 pw=0 time=5767 us) 1 HASH JOIN (cr=77 pr=0 pw=0 time=5756 us) 1028 HASH JOIN (cr=70 pr=0 pw=0 time=8692 us) 9 TABLE ACCESS FULL TS$ (cr=15 pr=0 pw=0 time=335 us) 1028 TABLE ACCESS FULL USER$ (cr=55 pr=0 pw=0 time=2140 us) 4 TABLE ACCESS FULL TS$ (cr=7 pr=0 pw=0 time=56 us) ******************************************************************************** select /* TAG */ substr( username, :"SYS_B_0", :"SYS_B_1" ) from all_users au2 where rownum = :"SYS_B_2" call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 85 0 1 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 4 0.00 0.00 0 85 0 1 Misses in library cache during parse: 0 Optimizer mode: ALL_ROWS Parsing user id: 412 Rows Row Source Operation ------- --------------------------------------------------- 1 COUNT (cr=85 pr=0 pw=0 time=3309 us) 1 FILTER (cr=85 pr=0 pw=0 time=3301 us) 1028 HASH JOIN (cr=85 pr=0 pw=0 time=5343 us) 1028 HASH JOIN (cr=70 pr=0 pw=0 time=7398 us) 9 TABLE ACCESS FULL TS$ (cr=15 pr=0 pw=0 time=148 us) 1028 TABLE ACCESS FULL USER$ (cr=55 pr=0 pw=0 time=1079 us) 9 TABLE ACCESS FULL TS$ (cr=15 pr=0 pw=0 time=90 us)

CHAPTER 1 ■ DEVELOPING SUCCESSFUL ORACLE APPLICATIONS 43<br />

ops$tkyte@ORA10G> select /* TAG */ substr( username, 1, 1 )<br />

2 from all_users au1<br />

3 where rownum = 1;<br />

S<br />

-<br />

B<br />

ops$tkyte@ORA10G> alter session set cursor_sharing=force;<br />

Session altered.<br />

ops$tkyte@ORA10G> select /* TAG */ substr( username, 1, 1 )<br />

2 from all_users au2<br />

3 where rownum = 1;<br />

SUBSTR(USERNAME,1,1)<br />

------------------------------<br />

B<br />

What happened there? Why is the column reported by SQL*Plus suddenly so large for the<br />

second query, which is arguably the same query? If we look at what the cursor sharing setting<br />

did for us, it (<strong>and</strong> something else) will become obvious:<br />

ops$tkyte@ORA10G> select sql_text from v$sql<br />

2 where sql_text like 'select /* TAG */ %';<br />

SQL_TEXT<br />

-------------------------------------------------------------------------------<br />

select /* TAG */ substr( username, 1, 1 ) from all_users au1 where rownum =<br />

1<br />

select /* TAG */ substr( username, :"SYS_B_0", :"SYS_B_1" )<br />

2 where rownum = :"SYS_B_2"<br />

from all_users au<br />

The cursor sharing removed information from the query. It found every literal, including<br />

the parameters to the built-in substring function, which were constants we were using. It<br />

removed them from the query <strong>and</strong> replaced them with bind variables. The SQL engine no<br />

longer knows that the column is a substring of length 1—it is of indeterminate length. Also,<br />

you can see that where rownum = 1 is now bound as well. That seems like a good idea; however,<br />

the optimizer has just had some important information removed. It no longer knows that “this<br />

query will retrieve a single row”; it now believes “this query will return the first N rows <strong>and</strong> N<br />

could be any number at all.” In fact, if you run these queries with SQL_TRACE=TRUE, you will find<br />

the query plans used by each query <strong>and</strong> the amount of work they perform to be very different.<br />

Consider the following:<br />

select /* TAG */ substr( username, 1, 1 )<br />

from all_users au1<br />

where rownum = 1

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!