Oracle
 sql >> Database >  >> RDS >> Oracle

Differenza non trascurabile del piano di esecuzione con Oracle quando si utilizza jdbc Timestamp o Date

Quindi il fatto è che i timestamp e le date Oracle sono due tipi di dati diversi. Per confrontare un timestamp con una data, Oracle deve eseguire una conversione - quella INTERNAL_FUNCTION(). La decisione di progettazione interessante è che Oracle converte la colonna della tabella anziché il valore passato, il che significa che la query non utilizza più l'indice.

Sono stato in grado di riprodurre il tuo scenario in SQL*Plus, quindi non è un problema con l'utilizzo di java.sql.Timestamp . Trasmettere i timestamp passati alle date risolve il problema...

SQL> explain plan for
  2      select * from test1
  3      where d1 > cast(to_timestamp('01-MAY-2011 00:00:00.000', 'DD-MON-YYYY Hh24:MI:SS.FF') as date)
  4       and d2 > cast(to_timestamp('01-JUN-2011 23:59:59.999', 'DD-MON-YYYY Hh24:MI:SS.FF') as date)
  5  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
-----------------------------------------------------------
Plan hash value: 1531258174

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    25 |   500 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST1 |    25 |   500 |     3   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T1_I  |     1 |       |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------    
   2 - access("D1">CAST(TO_TIMESTAMP('01-MAY-2011 00:00:00.000','DD-MON-YYYY
              Hh24:MI:SS.FF') AS date) AND "D2">CAST(TO_TIMESTAMP('01-JUN-2011
              23:59:59.999','DD-MON-YYYY Hh24:MI:SS.FF') AS date) AND "D1" IS NOT NULL)
       filter("D2">CAST(TO_TIMESTAMP('01-JUN-2011 23:59:59.999','DD-MON-YYYY
              Hh24:MI:SS.FF') AS date))

18 rows selected.

SQL>

Ma non credo che questo ti aiuti:sarebbe invece più facile passare semplicemente le date.

È interessante notare che la creazione di un indice basato su funzioni che trasmette le colonne della data ai timestamp non aiuta. Il INTERNAL_FUNCTION() la chiamata non è riconosciuta come CAST() e l'indice viene ignorato. Tentativo di creare un indice usando INTERNAL_FUNCTION() scaglia un ORA-00904.