Я бы рекомендовал использовать PreparedStatement практически каждый раз, когда вы передаете параметры, независимо от того, будете ли вы повторно использовать оператор. На практике я использую PreparedStatement для всего, кроме вызовов процедур, и позволяю БД и драйверу JDBC решать, что и как кэшировать. Вызовы процедур должны использовать CallableStatement для обработки отсутствия согласованного синтаксиса вызовов процедур между базами данных.
В PostgreSQL драйвер JDBC кэширует подготовленные операторы на стороне клиента, пока не будет достигнут определенный порог повторного использования. В этот момент выдается серверная команда PREPARE, и в будущих выполнениях используется подготовленный оператор на стороне сервера и его кэшированный план. Это может иметь некоторые ... интересные ... и неожиданные эффекты из-за статистического планировщика запросов PostgreSQL. Если ваша таблица имеет определенное распределение значений (или плохую статистику из-за отсутствия ANALYZE, неправильного random_page_cost или слишком низкого порога статистики), планировщик может выбрать другой и более медленный план запроса, если у него есть неизвестный параметр, который он выбрал бы, если бы он знал фактическую ценность, которую вы искали. Если вы столкнулись с внезапным и значительным замедлением запросов после 5-го (по умолчанию) повторения определенного оператора, это может вас укусить, и вы можете обойти это, отключив серверную PREPARE в PgJDBC , В настоящее время ведется работа по выявлению этих проблемных ситуаций на сервере путем проверки того, имеет ли конкретный параметр очень отличающиеся характеристики от случая с неизвестным значением, но AFAIK еще не достиг HEAD. Смотри также этот вопрос . Найдите дополнительную информацию в списке рассылки pgsql-general и stackOverflow.