Estoy analizando los planes de ejecución de Oracle y encontré un hecho sorprendente. Mira esta consulta. La sugerencia es sólo para mostrar que tengo un índice y yo esperaría que Oracle pueda usarlo para escaneo de rangos:Diferencia de plan de ejecución no despreciable con Oracle al usar jdbc Timestamp o Fecha
// execute_at is of type DATE.
PreparedStatement stmt = connection.prepareStatement(
"SELECT /*+ index(my_table my_index) */ * " +
"FROM my_table " +
"WHERE execute_at > ? AND execute_at < ?");
Estos dos fijaciones como resultado un comportamiento completamente diferente (para excluir temas Echar un vistazo variable de enlace, en realidad forzadas dos-análisis sintácticos duras):
// 1. with timestamps
stmt.setTimestamp(1, start);
stmt.setTimestamp(2, end);
// 2. with dates
stmt.setDate(1, start);
stmt.setDate(2, end);
1) con marcas de tiempo, consigo un INDEX FULL SCAN
y por lo tanto un filtro predicado
--------------------------------------------------------------
| 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<:2)"
3 - filter((INTERNAL_FUNCTION(""EXECUTE_AT"")>:1 AND
INTERNAL_FUNCTION(""EXECUTE_AT"")<:2))
2) Con fechas, tengo la gran INDEX RANGE SCAN
mejor acceso y un predicado
--------------------------------------------------------------
| 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<:2)"
3 - access(""EXECUTE_AT"">:1 AND ""EXECUTE_AT""<:2)
Ahora mi ejemplo es sólo un ejemplo. La consulta real es mucho más compleja, donde es esencial tener RANGE SCANS
o UNIQUE SCANS
(según el predicado) en lugar de FULL SCANS
.
¿Hay algo que esté malentendiendo aquí? ¿Alguien puede indicarme la mejor solución/práctica? Porque en el mundo de Java, creo que java.sql.Timestamp
es mucho más adecuado, pero la mayoría de nuestras columnas son del tipo DATE
de Oracle. Estamos usando Java 6 y Oracle 11g
Nota, me encontré con una pregunta similar aquí: http://stackoverflow.com/questions/1945603/why- is-oracle-so-slow-when-i-pass-a-java-sql-timestamp-for-a-date-column/6620643 –