sql >> Databáze >  >> RDS >> Oracle

Nezanedbatelný rozdíl v prováděcím plánu oproti Oracle při použití jdbc Timestamp nebo Date

Jde o to, že časová razítka Oracle a data Oracle jsou dva různé datové typy. Aby bylo možné porovnat časové razítko s datem, musí Oracle spustit konverzi – tedy INTERNAL_FUNCTION(). Zajímavým návrhovým rozhodnutím je, že Oracle převádí sloupec tabulky spíše než předávanou hodnotu, což znamená, že dotaz již nepoužívá index.

Byl jsem schopen reprodukovat váš scénář v SQL*Plus, takže není problém s použitím java.sql.Timestamp . Odesílání předaných časových razítek na data problém vyřeší...

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>

Ale nemyslím si, že by vám to nějak pomohlo:bylo by snazší místo toho jen předávat data.

Je zajímavé, že vytvoření indexu založeného na funkcích přetypování sloupců data na časová razítka nepomáhá. INTERNAL_FUNCTION() volání nebylo rozpoznáno jako CAST() a index je ignorován. Pokus o vytvoření indexu pomocí INTERNAL_FUNCTION() mrští ORA-00904.



  1. Udělení přístupu uživatele msdb k profilu pošty databáze v SQL Server (T-SQL)

  2. Jak vytvořit uživatele pro db v postgresql?

  3. Oracle Apex 5.0 – Zobrazení statického obrazu

  4. Jak najít duplicitní řádky v SQL?