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 11 ■ INDEXES 477 we’ll see that Oracle stops seeing the skip scan as being a sensible plan. It would have 256 mini indexes to inspect, and it opts for a full table scan to find our row: ops$tkyte@ORA10GR1> set autotrace traceonly explain ops$tkyte@ORA10GR1> select * from t t1 where object_id = 42; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=158 Card=1 Bytes=95) 1 0 TABLE ACCESS (FULL) OF 'T' (TABLE) (Cost=158 Card=1 Bytes=95) Case 2 We’re using a SELECT COUNT(*) FROM T query (or something similar) and we have a B*Tree index on table T. However, the optimizer is full scanning the table, rather than counting the (much smaller) index entries. In this case, the index is probably on a set of columns that can contain nulls. Since a totally null index entry would never be made, the count of rows in the index will not be the count of rows in the table. Here the optimizer is doing the right thing—it would get the wrong answer if it used the index to count rows. Case 3 For an indexed column, we query using the following: select * from t where f(indexed_column) = value and find that the index on INDEX_COLUMN is not used. This is due to the use of the function on the column. We indexed the values of INDEX_COLUMN, not the value of F(INDEXED_COLUMN). The ability to use the index is curtailed here. We can index the function if we choose to do it. Case 4 We have indexed a character column. This column contains only numeric data. We query using the following syntax: select * from t where indexed_column = 5 Note that the number 5 in the query is the constant number 5 (not a character string). The index on INDEXED_COLUMN is not used. This is because the preceding query is the same as the following: select * from t where to_number(indexed_column) = 5 We have implicitly applied a function to the column and, as noted in case 3, this will preclude the use of the index. This is very easy to see with a small example. In this example, we’re going to use the built-in package DBMS_XPLAN. This package is available only with Oracle9i Release 2 and above (in Oracle9i Release 1, we will use AUTOTRACE instead to see the plan easily, but we will not see the predicate information—that is only available in Oracle9i Release 2 and above):

478 CHAPTER 11 ■ INDEXES ops$tkyte@ORA10GR1> create table t ( x char(1) constraint t_pk primary key, 2 y date ); Table created. ops$tkyte@ORA10GR1> insert into t values ( '5', sysdate ); 1 row created. ops$tkyte@ORA10GR1> delete from plan_table; 3 rows deleted. ops$tkyte@ORA10GR1> explain plan for select * from t where x = 5; Explained. ops$tkyte@ORA10GR1> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT ------------------------------------------ Plan hash value: 749696591 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 12 | 2 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| T | 1 | 12 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(TO_NUMBER("X")=5) As you can see, it full scanned the table, and even if we were to hint the query ops$tkyte@ORA10GR1> explain plan for select /*+ INDEX(t t_pk) */ * from t 2 where x = 5; Explained. ops$tkyte@ORA10GR1> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT ------------------------------------ Plan hash value: 3473040572 ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 12 | 34 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 12 | 34 (0)| 00:00:01 | |* 2 | INDEX FULL SCAN | T_PK | 1 | | 26 (0)| 00:00:01 | ------------------------------------------------------------------------------------

478<br />

CHAPTER 11 ■ INDEXES<br />

ops$tkyte@ORA10GR1> create table t ( x char(1) constraint t_pk primary key,<br />

2 y date );<br />

Table created.<br />

ops$tkyte@ORA10GR1> insert into t values ( '5', sysdate );<br />

1 row created.<br />

ops$tkyte@ORA10GR1> delete from plan_table;<br />

3 rows deleted.<br />

ops$tkyte@ORA10GR1> explain plan for select * from t where x = 5;<br />

Explained.<br />

ops$tkyte@ORA10GR1> select * from table(dbms_xplan.display);<br />

PLAN_TABLE_OUTPUT<br />

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

Plan hash value: 749696591<br />

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

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |<br />

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

| 0 | SELECT STATEMENT | | 1 | 12 | 2 (0)| 00:00:01 |<br />

|* 1 | TABLE ACCESS FULL| T | 1 | 12 | 2 (0)| 00:00:01 |<br />

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

Predicate Information (identified by operation id):<br />

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

1 - filter(TO_NUMBER("X")=5)<br />

As you can see, it full scanned the table, <strong>and</strong> even if we were to hint the query<br />

ops$tkyte@ORA10GR1> explain plan for select /*+ INDEX(t t_pk) */ * from t<br />

2 where x = 5;<br />

Explained.<br />

ops$tkyte@ORA10GR1> select * from table(dbms_xplan.display);<br />

PLAN_TABLE_OUTPUT<br />

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

Plan hash value: 3473040572<br />

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

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |<br />

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

| 0 | SELECT STATEMENT | | 1 | 12 | 34 (0)| 00:00:01 |<br />

| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 12 | 34 (0)| 00:00:01 |<br />

|* 2 | INDEX FULL SCAN | T_PK | 1 | | 26 (0)| 00:00:01 |<br />

------------------------------------------------------------------------------------

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

Saved successfully!

Ooh no, something went wrong!