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.

CHAPTER 11 ■ INDEXES 467<br />

Caveat on CASE<br />

There is a bug in certain <strong>Oracle</strong> releases whereby a function referenced in a function-based<br />

index is rewritten in a manner that prevents the index from apparently being used. For example,<br />

the previous CASE statement<br />

Case when temporary = 'N' then 'N' end<br />

will silently be rewritten into the more efficient<br />

CASE "TEMPORARY" WHEN 'N' THEN 'N' END<br />

But this function doesn’t match the one we created anymore, so queries will not be able to<br />

use it. This simple test case, performed in 10.1.0.3 <strong>and</strong> then again in 10.1.0.4 (where it is corrected),<br />

demonstrates this (in 10.1.0.3):<br />

ops$tkyte@ORA10GR1> create table t ( x int );<br />

Table created.<br />

ops$tkyte@ORA10GR1> create index t_idx on<br />

2 t( case when x = 42 then 1 end );<br />

Index created.<br />

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

ops$tkyte@ORA10GR1> select /*+ index( t t_idx ) */ *<br />

2 from t<br />

3 where (case when x = 42 then 1 end ) = 1;<br />

Execution Plan<br />

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

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

1 0 TABLE ACCESS (FULL) OF 'T' (TABLE) (Cost=2 Card=1 Bytes=13)<br />

It would appear that the function-based index just won’t work <strong>and</strong> isn’t available. But in<br />

fact, the FBI is available, because the underlying function was rewritten, <strong>and</strong> we can verify this<br />

by peeking at the view USER_IND_EXPRESSIONS to see what <strong>Oracle</strong> has rewritten it to<br />

ops$tkyte@ORA10GR1> select column_expression<br />

2 from user_ind_expressions<br />

3 where index_name = 'T_IDX';<br />

COLUMN_EXPRESSION<br />

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

CASE "X" WHEN 42 THEN 1 END<br />

In <strong>Oracle</strong> 10.1.0.4, the rewrite still takes place in the function-based index, but the index<br />

use takes place:<br />

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

ops$tkyte@ORA10G> select /*+ index( t t_idx ) */ *<br />

2 from t<br />

3 where (case when x = 42 then 1 end ) = 1;

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

Saved successfully!

Ooh no, something went wrong!