Возможно, это не относится к вашей конкретной ситуации, но я хотел дать другое возможное объяснение тому, кто ищет эту проблему.
У меня просто была похожая проблема, когда запрос, выполняемый непосредственно в SQL Server, занимал 1 минуту, в то время как тот же запрос занимал 5 минут через подготовленный компонент состояния Java. Я проследил это до того, что это было сделано как подготовленное заявление.
Когда вы выполняете запрос непосредственно в SQL Server, вы предоставляете ему непараметрический запрос, в котором он знает все критерии поиска во время оптимизации. В моем случае мои критерии поиска включали диапазон дат, и SQL-сервер смог посмотреть на него, решить, что «диапазон дат огромен, давайте не будем использовать индекс дат», и тогда он выбрал что-то намного лучшее.
Когда я выполняю тот же запрос через подготовленный оператор Java, в то время, когда SQL Server оптимизирует запрос, вы еще не предоставили ему ни одного из значений параметра, поэтому он должен угадать, какой индекс использовать , В случае моего диапазона дат, если он оптимизируется для небольшого диапазона, и я задаю ему большой диапазон, он будет работать медленнее, чем мог бы. Точно так же, если он оптимизируется для большого диапазона, а я даю ему маленький, он снова будет работать медленнее, чем мог бы.
Чтобы продемонстрировать, что это действительно было проблемой, в качестве эксперимента я попытался дать ему подсказки о том, что оптимизировать для использования опции «OPTIMIZE FOR» в SQL Server. Когда я сказал ему использовать крошечный диапазон дат, мой Java-запрос (который на самом деле имел широкий диапазон дат) фактически занимал в два раза больше времени, чем раньше (10 минут, по сравнению с 5 минутами раньше, и 1 минутой в SQL Server) ). Когда я сообщил точные даты для оптимизации, время выполнения было одинаковым для подготовленного Java-оператора.
Таким образом, я решил жестко запрограммировать точные даты в запросе. Это сработало для меня, потому что это было одноразовое заявление. PreparedStatement не предназначался для повторного использования, а просто для параметризации значений, чтобы избежать внедрения SQL. Поскольку эти даты были получены из объекта java.sql.Date, мне не пришлось беспокоиться о значениях дат, содержащих код внедрения.
Тем не менее, для заявления, которое ДОЛЖНО быть повторно использовано, жесткое кодирование дат не будет работать. Возможно, лучшим вариантом для этого было бы создание нескольких подготовленных выписок, оптимизированных для разных диапазонов дат (один на день, один на неделю, один на месяц, один на год и один на десятилетие ... или, может быть, вы нужны только 2 или 3 варианта ... я не знаю) и затем для каждого запроса выполните один подготовленный оператор, чей временной диапазон лучше всего соответствует диапазону в реальном запросе.
Конечно, это работает только в том случае, если ваши диапазоны дат распределены равномерно. Если 80% ваших записей были в прошлом году, а 20% - разбросаны за предыдущие 10 лет, то выполнение «нескольких запросов на основе размера диапазона» может оказаться не лучшим решением. Вы должны оптимизировать свои запросы на основе определенных диапазонов или чего-то еще. Вы должны выяснить это через испытание.