Need to understand why optimizer unable to use index in case of "OR" whenn we set one partition index to unusable, the same query with between uses index.
“OR” condition fetch less data comparing to “BETWEEN” still oracle optimizer unable to use indexes in case of “OR”
1. Created local index on partitioned table
2. ndex partition t_dec_2009 set to unusable
-- Partitioned local Index behavior with “OR” and with “BETWEEN”
SQL> CREATE TABLE t (
2 id NUMBER NOT NULL,
3 d DATE NOT NULL,
4 n NUMBER NOT NULL,
5 pad VARCHAR2(4000) NOT NULL
6 )
7 PARTITION BY RANGE (d) (
8 PARTITION t_jan_2009 VALUES LESS THAN (to_date('2009-02-01','yyyy-mm-dd')),
9 PARTITION t_feb_2009 VALUES LESS THAN (to_date('2009-03-01','yyyy-mm-dd')),
10 PARTITION t_mar_2009 VALUES LESS THAN (to_date('2009-04-01','yyyy-mm-dd')),
11 PARTITION t_apr_2009 VALUES LESS THAN (to_date('2009-05-01','yyyy-mm-dd')),
12 PARTITION t_may_2009 VALUES LESS THAN (to_date('2009-06-01','yyyy-mm-dd')),
13 PARTITION t_jun_2009 VALUES LESS THAN (to_date('2009-07-01','yyyy-mm-dd')),
14 PARTITION t_jul_2009 VALUES LESS THAN (to_date('2009-08-01','yyyy-mm-dd')),
15 PARTITION t_aug_2009 VALUES LESS THAN (to_date('2009-09-01','yyyy-mm-dd')),
16 PARTITION t_sep_2009 VALUES LESS THAN (to_date('2009-10-01','yyyy-mm-dd')),
17 PARTITION t_oct_2009 VALUES LESS THAN (to_date('2009-11-01','yyyy-mm-dd')),
18 PARTITION t_nov_2009 VALUES LESS THAN (to_date('2009-12-01','yyyy-mm-dd')),
19 PARTITION t_dec_2009 VALUES LESS THAN (to_date('2010-01-01','yyyy-mm-dd'))
20 );
SQL> INSERT INTO t
2 SELECT rownum, to_date('2009-01-01','yyyy-mm-dd')+rownum/274, mod(rownum,11), rpad('*',100,'*')
3 FROM dual
4 CONNECT BY level <= 100000;
SQL> CREATE INDEX i ON t (d) LOCAL;
SQL> execute dbms_stats.gather_table_stats(user,'T')
-- Mark partition t_dec_2009 to unusable:
SQL> ALTER INDEX i MODIFY PARTITION t_dec_2009 UNUSABLE;
--- Let’s check whether the usable index partition can be used to apply a restriction: BETWEEN
SQL> SELECT count(d)
FROM t
WHERE d BETWEEN to_date('2009-01-01 23:00:00','yyyy-mm-dd hh24:mi:ss')
AND to_date('2009-02-02 01:00:00','yyyy-mm-dd hh24:mi:ss');
SQL> SELECT * FROM table(dbms_xplan.display_cursor(format=>'basic +partition'));
--------------------------------------------------------
| Id | Operation | Name | Pstart| Pstop |
--------------------------------------------------------
| 0 | SELECT STATEMENT | | | |
| 1 | SORT AGGREGATE | | | |
| 2 | PARTITION RANGE SINGLE| | 12 | 12 |
| 3 | INDEX RANGE SCAN | I | 12 | 12 |
--------------------------------------------------------
--- Let’s check whether the usable index partition can be used to apply a restriction: OR
SQL> SELECT count(d)
FROM t
WHERE
(
(d >= to_date('2009-01-01 23:00:00','yyyy-mm-dd hh24:mi:ss') and d <= to_date('2009-01-01 23:59:59','yyyy-mm-dd hh24:mi:ss'))
or
(d >= to_date('2009-02-02 01:00:00','yyyy-mm-dd hh24:mi:ss') and d <= to_date('2009-02-02 02:00:00','yyyy-mm-dd hh24:mi:ss'))
);
SQL> SELECT * FROM table(dbms_xplan.display_cursor(format=>'basic +partition'));
----------------------------------------------------
| Id | Operation | Name | Pstart| Pstop |
----------------------------------------------------
| 0 | SELECT STATEMENT | | | |
| 1 | SORT AGGREGATE | | | |
| 2 | PARTITION RANGE OR| |KEY(OR)|KEY(OR)|
| 3 | TABLE ACCESS FULL| T |KEY(OR)|KEY(OR)|
----------------------------------------------------
“OR” condition fetch less data comparing to “BETWEEN” still oracle optimizer unable to use indexes in case of “OR”
Regards,
Sachin B.