sql >> Base de Datos >  >> RDS >> Oracle

Diferencia no despreciable del plan de ejecución con Oracle cuando se usa jdbc Timestamp o Date

Entonces, la cuestión es que las marcas de tiempo de Oracle y las fechas de Oracle son dos tipos de datos diferentes. Para comparar una marca de tiempo con una fecha, Oracle tiene que ejecutar una conversión:INTERNAL_FUNCTION(). La decisión de diseño interesante es que Oracle convierte la columna de la tabla en lugar del valor pasado, lo que significa que la consulta ya no usa el índice.

He podido reproducir su escenario en SQL*Plus, por lo que no hay problema con el uso de java.sql.Timestamp . Convertir las marcas de tiempo pasadas en fechas resuelve el 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>

Pero no creo que eso te ayude en nada:sería más fácil pasar fechas en su lugar.

Curiosamente, la creación de un índice basado en funciones que convierta las columnas de fecha en marcas de tiempo no ayuda. El INTERNAL_FUNCTION() la llamada no se reconoce como CAST() y el índice es ignorado. Intentando construir un índice usando INTERNAL_FUNCTION() lanza un ORA-00904.