JDBC prepared statements on application server suddenly select a generic plan causing a 15× slowdown for partitioned table queries
Environment
Java Spring Boot application (OpenJDK 11, PostgreSQL JDBC driver 42.x) connecting via a connection pool (HikariCP) to PostgreSQL 13 on Debian. The app issues parameterized queries against a large date-partitioned table using PreparedStatement.setTimestamp(). Production query latency jumped from ~200 ms to multiple seconds for queries that filter on the partition key.
Symptoms
Only requests issued via application (prepared statements through JDBC) are slow; identical SQL copy-pasted and executed in psql (with explicit literal values) returns in ~200 ms. EXPLAIN (ANALYZE, BUFFERS) shows that prepared statement executions use a generic plan with sequential scan across partitions instead of index-constraint exclusion plan. Query times worsen during peak load and remain fast when run in psql.
Observations
pg_stat_activity shows large number of active prepared statements. Prepared statement PLANS in pg_prepared_statements (when present) show generic_plan=true. Server logs show 'plan is generic' messages when log_min_duration_sampled enabled. Application connection pool uses transaction-level pooling and may reuse connections; app uses PreparedStatement for many slightly different parameter types (sometimes setObject). No recent schema changes; stats were updated recently via autovacuum. Reproduced with a local JDBC minimal test harness showing same generic plan behavior when using setTimestamp vs hard-coded literal.
Already attempted
Disabled HikariCP statement caching and forced the application to use simple query mode by setting 'prepareThreshold=0' in the JDBC URL; prepared queries returned to fast plans. Increased default_statistics_target and ran ANALYZE on partitions — partial improvement for some queries. Restarted database to clear plan caches and observed no lasting improvement until prepareThreshold was zeroed. Upgraded JDBC driver in a staging environment but issue persisted until disabling server-side prepared statements.
Question
What is the safest way to configure JDBC/connection pool or PostgreSQL so that parameterized queries against partitioned tables use custom/bound plans (or re-plan per parameter) without disabling all prepared statements? Are there server-side settings or driver parameters to prefer custom plans for partition pruning use-cases, and what are the trade-offs?
Verified community troubleshooting
No answers yet..
Incident analysis
Most likely causes
Summary
Suggested Fixes
Continue troubleshooting
Related troubles
Matched from the title, description and tags
- Databases41% match
PostgreSQL prepared statements pick a generic plan after ANALYZE on a partitioned table, causing 10× slower execution
Open0 answers - Databases31% match
JDBC queries 10× slower than psql: fast in psql, slow via HikariCP in app server
Open0 answers - Databases27% match
JDBC clients fail with 'bind message supplies 0 parameters' after ALTER COLUMN type; prepared statements misbehave on PostgreSQL 14
Open0 answers - Databases25% match
Partitioned-table queries run fast in psql but 8–12× slower when routed through PgBouncer transaction pooling
Open0 answers