sql >> データベース >  >> RDS >> Oracle

jdbcTimestampまたはDateを使用する場合のOracleとの無視できない実行プランの違い

    つまり、OracleのタイムスタンプとOracleの日付は2つの異なるデータ型です。タイムスタンプを日付と比較するために、Oracleは変換を実行する必要があります-そのINTERNAL_FUNCTION()。興味深い設計上の決定は、Oracleが渡された値ではなくテーブル列を変換することです。これは、クエリがインデックスを使用しなくなったことを意味します。

    SQL * Plusでシナリオを再現できたので、java.sql.Timestampを使用しても問題ありません。 。渡されたタイムスタンプを日付にキャストすると、問題は解決します...

    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>
    

    しかし、それがあなたに役立つとは思いません。代わりに日付を渡す方が簡単でしょう。

    興味深いことに、日付列をタイムスタンプにキャストする関数ベースのインデックスを作成しても役に立ちません。 INTERNAL_FUNCTION() 呼び出しはCAST()として認識されません インデックスは無視されます。 INTERNAL_FUNCTION()を使用してインデックスを作成しようとしています ORA-00904を投げます。



    1. COALESCEとISNULLのどちらが速いですか?

    2. SQLServerで左アンチセミ結合を実行する方法

    3. ここでEXECUTEIMMEDIATEが必要なのはなぜですか?

    4. パフォーマンステストの方法論:新しい方法の発見