Note that there are some explanatory texts on larger screens.

plurals
  1. PONon-negligible execution plan difference with Oracle when using jdbc Timestamp or Date
    primarykey
    data
    text
    <p>I'm analysing Oracle execution plans and found an astonishing fact. Check out this query. The hint is just to display that I have an index and I'd expect Oracle to use it for range scans:</p> <pre class="lang-java prettyprint-override"><code>// execute_at is of type DATE. PreparedStatement stmt = connection.prepareStatement( "SELECT /*+ index(my_table my_index) */ * " + "FROM my_table " + "WHERE execute_at &gt; ? AND execute_at &lt; ?"); </code></pre> <p>These two bindings result in entirely different behaviour (to exclude bind variable peeking issues, I actually enforced two hard-parses):</p> <pre class="lang-java prettyprint-override"><code>// 1. with timestamps stmt.setTimestamp(1, start); stmt.setTimestamp(2, end); // 2. with dates stmt.setDate(1, start); stmt.setDate(2, end); </code></pre> <p>1) With timestamps, I get an <code>INDEX FULL SCAN</code> and thus a filter predicate</p> <pre><code>-------------------------------------------------------------- | Id | Operation | Name | -------------------------------------------------------------- | 0 | SELECT STATEMENT | | |* 1 | FILTER | | | 2 | TABLE ACCESS BY INDEX ROWID| my_table | |* 3 | INDEX FULL SCAN | my_index | -------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(:1&lt;:2)" 3 - filter((INTERNAL_FUNCTION(""EXECUTE_AT"")&gt;:1 AND INTERNAL_FUNCTION(""EXECUTE_AT"")&lt;:2)) </code></pre> <p>2) With dates, I get the much better <code>INDEX RANGE SCAN</code> and an access predicate</p> <pre><code>-------------------------------------------------------------- | Id | Operation | Name | -------------------------------------------------------------- | 0 | SELECT STATEMENT | | |* 1 | FILTER | | | 2 | TABLE ACCESS BY INDEX ROWID| my_table | |* 3 | INDEX RANGE SCAN | my_index | -------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(:1&lt;:2)" 3 - access(""EXECUTE_AT""&gt;:1 AND ""EXECUTE_AT""&lt;:2) </code></pre> <p>Now my example is just an example. The real query is much more complex, where it is essential to have <code>RANGE SCANS</code> or <code>UNIQUE SCANS</code> (depending on the predicate) rather than <code>FULL SCANS</code>.</p> <p>Is there something I'm misunderstanding here? Can someone point me to the best solution/practice? Because in the Java world, I think that <code>java.sql.Timestamp</code> is much more suitable but most of our columns are of Oracle's <code>DATE</code> type. We're using Java 6 and Oracle 11g</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload