Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Diferença não negligenciável do plano de execução com o Oracle ao usar o carimbo de data e hora jdbc ou data


Então, o fato é que os carimbos de data e hora Oracle e as datas Oracle são dois tipos de dados diferentes. Para comparar um carimbo de data/hora com uma data, o Oracle precisa executar uma conversão - que INTERNAL_FUNCTION(). A decisão de design interessante é que o Oracle converte a coluna da tabela em vez do valor passado, o que significa que a consulta não usa mais o índice.

Consegui reproduzir seu cenário no SQL*Plus, portanto, não há problema em usar java.sql.Timestamp . A conversão dos timestamps passados ​​para datas resolve o 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>

Mas acho que isso não ajuda em nada:seria mais fácil apenas passar datas.

Curiosamente, construir um índice baseado em função que converte as colunas de data em carimbos de data/hora não ajuda. O INTERNAL_FUNCTION() chamada não é reconhecida como CAST() e o índice é ignorado. Tentando construir um índice usando INTERNAL_FUNCTION() lança um ORA-00904.