05.11.2015 Views

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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

458<br />

CHAPTER 11 ■ INDEXES<br />

ops$tkyte@ORA10G> set autotrace traceonly explain<br />

ops$tkyte@ORA10G> select *<br />

2 from emp<br />

3 where upper(ename) = 'KING';<br />

Execution Plan<br />

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

0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=2 Bytes=92)<br />

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (TABLE) (Cost=2 Card=2 Bytes=92)<br />

2 1 INDEX (RANGE SCAN) OF 'EMP_UPPER_IDX' (INDEX) (Cost=1 Card=2)<br />

will make use of this index, gaining the performance boost an index can deliver. Before this<br />

feature was available, every row in the EMP table would have been scanned, uppercased, <strong>and</strong><br />

compared. In contrast, with the index on UPPER(ENAME), the query takes the constant KING to<br />

the index, range scans a little data, <strong>and</strong> accesses the table by rowid to get the data. This is<br />

very fast.<br />

This performance boost is most visible when indexing user-written functions on<br />

columns. <strong>Oracle</strong> 7.1 added the ability to use user-written functions in SQL, so we could<br />

do something like this:<br />

SQL> select my_function(ename)<br />

2 from emp<br />

3 where some_other_function(empno) > 10<br />

4 /<br />

This was great because we could now effectively extend the SQL language to include<br />

application-specific functions. Unfortunately, however, the performance of the preceding<br />

query was a bit disappointing at times. Say the EMP table had 1,000 rows in it. The function<br />

SOME_OTHER_FUNCTION would be executed 1,000 times during the query, once per row. In addition,<br />

assuming the function took one-hundredth of a second to execute, this relatively simple<br />

query now takes at least ten seconds.<br />

Let’s look at a real example, where we’ll implement a modified SOUNDEX routine in PL/SQL.<br />

Additionally, we’ll use a package global variable as a counter in our procedure, which will<br />

allow us to execute queries that make use of the MY_SOUNDEX function <strong>and</strong> see exactly how<br />

many times it was called:<br />

ops$tkyte@ORA10G> create or replace package stats<br />

2 as<br />

3 cnt number default 0;<br />

4 end;<br />

5 /<br />

Package created.<br />

ops$tkyte@ORA10G> create or replace<br />

2 function my_soundex( p_string in varchar2 ) return varchar2<br />

3 deterministic<br />

4 as<br />

5 l_return_string varchar2(6) default substr( p_string, 1, 1 );<br />

6 l_char varchar2(1);

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

Saved successfully!

Ooh no, something went wrong!