sql >> Database >  >> RDS >> Oracle

Niet te verwaarlozen verschil in uitvoeringsplan met Oracle bij gebruik van jdbc Timestamp of Date

Het punt is dus dat Oracle-tijdstempels en Oracle-datums twee verschillende datatypes zijn. Om een ​​tijdstempel te vergelijken met een datum moet Oracle een conversie uitvoeren - die INTERNAL_FUNCTION(). De interessante ontwerpbeslissing is dat Oracle de tabelkolom converteert in plaats van de doorgegeven waarde, wat betekent dat de query niet langer de index gebruikt.

Ik heb je scenario kunnen reproduceren in SQL*Plus, dus het is geen probleem om java.sql.Timestamp te gebruiken . Het casten van de doorgegeven tijdstempels naar datums lost het probleem op...

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>

Maar ik denk niet dat je daar iets aan hebt:het zou gemakkelijker zijn om in plaats daarvan gewoon datums door te geven.

Interessant is dat het niet helpt om een ​​op functies gebaseerde index te bouwen die de datumkolommen cast naar tijdstempels. De INTERNAL_FUNCTION() oproep wordt niet herkend als een CAST() en de index wordt genegeerd. Een index proberen te bouwen met INTERNAL_FUNCTION() gooit een ORA-00904.



  1. Hoe kan ik een MySQL-database initialiseren met schema in een Docker-container?

  2. PostgreSQL 12-prestaties bewaken met OmniDB - deel 1

  3. Hoe krijg ik vroege toegang tot Oracle Java-updates, zodat ik mijn RIA kan testen en brandoefeningen kan vermijden wanneer deze updates openbaar worden gemaakt?

  4. Hoe to_date() werkt in PostgreSQL