У меня есть таблица с a DATE
столбец со временем (как обычно, в Oracle с тех пор нет a TIME
введите). Когда я запрашиваю тот столбец от JDBC, у меня есть две опции:
to_date()
java.sql.Timestamp
Обе работы подходов и имеют эксклюзивные области безобразия. Моя проблема состоит в том, когда я SELECT
данные луга. Вот два демонстрационных запроса:
select *
from TABLE
where TS between {ts '2009-12-08 00:00:00.000'} and {ts '2009-12-09 00:00:00.000'}
select *
from TABLE
where TS between trunc({ts '2009-12-08 00:00:00.000'}) and trunc({ts '2009-12-09 00:00:00.000'})
Обе работы запросов, возвратите те же результаты и произведите тот же самый вывод в EXPLAIN PLAN
. Это право индексы используется.
Только запросите, каждый выполняет 15 минут, в то время как второй запрос занимает 0,031 с. Почему это? Есть ли центральное место для фиксации этого, или сделать я должен проверить все свои запросы на этот столбец и сделать совершенно уверенными что trunc()
там? Как я устраняю эту проблему, когда я должен выбрать вниз к определенной секунде?
[РЕДАКТИРОВАНИЕ] таблица, делится, и я нахожусь на Oracle 10.2.0.
Я не понимаю, что на самом деле означает {ts '2009-12-08 00:00:00.000'}, так как это не Oracle SQL, насколько я знаю. Можете ли вы показать, какой именно запрос вы выполняете?
Одна из возможных проблем заключается в том, что вы указываете свой диапазон с миллисекундами. Тип ДАТЫ Oracle уменьшается только до секунд. (Используйте тип TIMESTAMP, если вам нужно хранить доли секунд). Но, возможно, это происходит в первом запросе, Oracle преобразует каждое значение DATE в TIMESTAMP для проведения сравнения с указанным ВРЕМЕНИРОВАНИЕМ. Во втором случае, он знает, что TRUNC() эффективно округлит ваше значение до чего-то, что может быть выражено как DATE, поэтому преобразование не требуется.
Если вы хотите избежать таких неявных преобразований, убедитесь, что вы всегда сравниваете подобное с подобным. например
select *
from my_table t
where t.ts between to_date('2009-12-08','YYYY-MM-DD') and to_date('2009-12-09','YYYY-MM-DD')
Некоторое время назад у меня была эта проблема на проекте и установка свойства соединения oracle.jdbc.V8Compatible=true исправила эту проблему.
Ссылка Dougman подсказывает, как ее установить:
Вы устанавливаете свойство соединения посредством добавление его в java.util.Properties переданный объект DriverManager.getConnection или к OracleDataSource.setConnectionProperties. Вы устанавливаете свойство системы по включая опцию -D в вашей яве командная строка.
java -Doracle.jdbc.V8Compatible="true". MyApp
Примечание для 11g и это свойство, очевидно, не используется.
С http://forums.oracle.com/forums/thread.jspa?messageID=1659839 :
Одно дополнительное примечание для тех, кто является используя 11gR1 (и дальше) JDBC тонкий драйвер: V8Совместимое соединение собственности больше не существует, так что ты не можешь полагаться на это, чтобы отправить ваш java.sql.Timestamp как SQLDATE. Что Однако вы можете сделать так:
setObject(i, aTimestamp, java.sql.Types.DATE) посылает данные как SQLDATE setObject(i, aDate) посылает данные как SQLDATE setDate(i, aDate) посылает данные как SQLDATE setDATE(i, aDATE) (нестандартная) посылает данные как SQLDATE setObject(i, aTimestamp) отправляет данные как SQLTIMESTAMP setTimestamp(i, aTimestamp) отправляет данные как SQLTIMESTAMP setObject(i, aTimestamp) отправляет данные как SQLTIMESTAMP setTIMESTAMP(i, aTIMESTAMP) (нестандартный) отправляет данные как SQLTIMESTAMP