Reputation: 22506
I have indexes on two columns of type Timestamp(2) START_DATE and END_DATE and a query with WHARE clause like:
WHERE C.START_DATE <= sysdate
AND sysdate <= C.END_DATE
The explain plan makes TABLE ACCESS FULL instead of Index range scan.
-If I change <=
to =
the index is used.
-If I change sysdate
to systimestamp
it's worse in the explain plan:
SYS_EXTRACT_UTC(INTERNAL_FUNCTION(C.START_DATE))<=SYS_EXTRACT_UTC(SYSTIMESTAMP(6))
with FULL SCAN again.
-Using TO_TIMESTAMP
brings the desired index range scan:
WHERE C.START_DATE <= TO_TIMESTAMP ('10-Sep-02 14:10:10.123000', 'DD-Mon-RR HH24:MI:SS.FF')
AND TO_TIMESTAMP ('10-Sep-02 14:10:10.123000', 'DD-Mon-RR HH24:MI:SS.FF') <= C.END_DATE
but I need to use the current date.
Can someone explain why that happens?
EDIT: These are simplified versions of the query, but the same behavior appears. Explain plans.
EXPLAIN PLAN FOR
select *
from communication c
WHERE C.CAMPAIGN_START_DATE <= sysdate
AND sysdate <= C.CAMPAIGN_END_DATE;
Plan hash value: 4120205924
-------------------------------------------
| Id | Operation | Name |
-------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS FULL| COMMUNICATION |
-------------------------------------------
.
EXPLAIN PLAN FOR
select *
from communication c
WHERE C.START_DATE = sysdate
AND sysdate = C.END_DATE;
Plan hash value: 1474125303
-------------------------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID | COMMUNICATION |
| 2 | BITMAP CONVERSION TO ROWIDS | |
| 3 | BITMAP AND | |
| 4 | BITMAP CONVERSION FROM ROWIDS| |
| 5 | INDEX RANGE SCAN | COMMUNICATION_START_DT |
| 6 | BITMAP CONVERSION FROM ROWIDS| |
| 7 | INDEX RANGE SCAN | COMMUNICATION_END_TD |
-------------------------------------------------------------------
Upvotes: 1
Views: 6389
Reputation: 48187
Did you try with today day in timestamp? TO_TIMESTAMP ('27-oct-15 14:10:10.123000'
? Doesnt make sense you compare the query using two different days.
My guess is using current date and <=
will mean check most of the rows anyway. That mean using the index wont give much benefit
Try this query.
SELECT COUNT(*)
and
SELECT COUNT(*)
FROM ....
WHERE C.START_DATE <= sysdate
AND sysdate <= C.END_DATE
If both COUNT(*)
are very similar mean there isnt any benefit on using the index because will need scan the full table anyway.
Upvotes: 3