Usage.......: @file_name
Description.: Why we need to avoid implicit data conversions on index columns in predicate.
Notes.......: index on VarChar2 columns
Parameters..:
Package.....: ._pkg
Modification History:
Date Who What
29-Oct-2010: Charlie(Yi): Create the file,
Goal
----
Show how implicit data conversions impact Effective Index Selectivity.
Prove that developers rely on implicit conversions is a bad practice.
Solution
--------
Create index on VarChar2 column(s), put number value in the predicate that use this index,
cause implicitly data type conversion.
E.g. TO_NUMBER(index_column) = n
Spec
----
cost = blevel +
ceiling(leaf_blocks * effective index selectivity) +
ceiling(clustering_factor * effective table selectivity)
Logical Reads(LIO) of index access = BLevel + leaf_blocks * effective index selectivity
Buffers is LIO in function dbms_xplan.display_cursor output.
See Page 62(91) of Book: [Cost-Based Oracle Fundamentals]
Result
------
cost = 1 , LIO = 2 , No data conversion
cost = 26, LIO = 28, data conversion, from char to number
Data flow
---------
Test case
---------
* ,
* ,
Setup
-----
See below SQL code.
Reference
---
QA..: You can send feedbacks or questions about this script to charlie.zhu1 gmail.com
blog: http://mujiang.blogspot.com/
ALTER SESSION SET STATISTICS_LEVEL=TYPICAL;
create table t
(
c1 VarChar2(5),
c2 VarChar2(7)
)
nologging;
create table t1
(
c1 varchar2(5),
n1 number(5)
)
nologging;
insert into t1(c1,n1) values('501',501);
insert /*+ append */ into t(c1,c2)
select mod(rownum,5), rownum
from dual
connect by level <=50000;
commit;
create unique index t_u1 on t(c1,c2) nologging;
exec dbms_stats.gather_table_stats(user,'t');
exec dbms_stats.gather_table_stats(user,'t1');
set serveroutput off
set linesize 200
ALTER SESSION SET STATISTICS_LEVEL=ALL;
REM -- use number value on VarChar2 index columns,
select * from t
where c1='1' and c2=(select n1 from t1);
SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL, '+cost iostats memstats last partition'));
----------------------------------------------------------
| Id | Operation | Name | Cost (%CPU)| Buffers |
----------------------------------------------------------
| 0 | SELECT STATEMENT | | 29 (100)| 35 |
|* 1 | INDEX RANGE SCAN | T_U1 | 26 (0)| 35 |
| 2 | TABLE ACCESS FULL| T1 | 3 (0)| 7 |
----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("C1"='1')
filter(TO_NUMBER("C2")=)
REM -- use string value on VarChar2 index columns,
select * from t
where c1='1' and c2=(select c1 from t1);
SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL, 'cost iostats memstats last partition'));
----------------------------------------------------------
| Id | Operation | Name | Cost (%CPU)| Buffers |
----------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 (100)| 9 |
|* 1 | INDEX UNIQUE SCAN | T_U1 | 1 (0)| 9 |
| 2 | TABLE ACCESS FULL| T1 | 3 (0)| 7 |
----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("C1"='1' AND "C2"=)
.
No comments:
Post a Comment