Oracle
 sql >> Base de données >  >> RDS >> Oracle

Différence de plan d'exécution non négligeable avec Oracle lors de l'utilisation de jdbc Timestamp ou Date

Donc, le fait est que les horodatages Oracle et les dates Oracle sont deux types de données différents. Afin de comparer un horodatage à une date, Oracle doit exécuter une conversion - cette INTERNAL_FUNCTION(). La décision de conception intéressante est qu'Oracle convertit la colonne de la table plutôt que la valeur transmise, ce qui signifie que la requête n'utilise plus l'index.

J'ai pu reproduire votre scénario dans SQL*Plus, donc ce n'est pas un problème avec l'utilisation de java.sql.Timestamp . La conversion des horodatages passés en dates résout le problème...

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>

Mais je ne pense pas que cela vous aide :il serait plus facile de simplement passer des rendez-vous à la place.

Il est intéressant de noter que la création d'un index basé sur des fonctions convertissant les colonnes de date en horodatages n'aide pas. Le INTERNAL_FUNCTION() l'appel n'est pas reconnu comme un CAST() et l'index est ignoré. Essayer de construire un index en utilisant INTERNAL_FUNCTION() lance un ORA-00904.