Почему Oracle является настолько медленной, когда я передаю java.sql. Метка времени для столбца DATE?

У меня есть таблица с a DATE столбец со временем (как обычно, в Oracle с тех пор нет a TIME введите). Когда я запрашиваю тот столбец от JDBC, у меня есть две опции:

  • Вручную преобразуйте значения с Oracle to_date()
  • Используйте a 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.

6
задан Aaron Digulla 22 December 2009 в 10:57
поделиться

2 ответа

Я не понимаю, что на самом деле означает {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')
3
ответ дан 9 December 2019 в 20:44
поделиться

Некоторое время назад у меня была эта проблема на проекте и установка свойства соединения 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
2
ответ дан 9 December 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: