perf(datasource): reuse query plans on core connections (#49)
Build, Test & Push Core Service / quality-check (push) Successful in 2m11s
Build, Test & Push Core Service / docker (push) Successful in 1m29s

Planning was 94% of Dashboard DB time, and prod never reused a plan.
Force generic plans and prepare on first use. Burst: 443 -> 229 ms.
This commit is contained in:
lobo committed 2026-10-20 11:41:31 +02:00
1 parent 6f2d7b4885
commit 4fbf572f32
3 files changed
+42

No files matched your search

+8
View File
@@ -909,6 +909,14 @@ duration, e.g. `GET /api/library/games 200 28 ms`. The pattern is `-` when no ha
routing). The line never holds ids, query strings, user data or tokens. `/actuator/**` is skipped. An exception
that leaves the filter chain is logged as `500`.
### Database connection settings
Every Core connection runs with `plan_cache_mode = force_generic_plan` and `prepareThreshold=1`
(`spring.datasource.hikari` in `application.yml`). Planning was 94% of the Dashboard DB time and prod never reused a
plan (few users, a new connection every 30 min). With a cached generic plan the Dashboard burst dropped from 443 to
229 ms on 2 CPUs (#49). Cost: the first burst on fresh connections costs about 100 ms more (cold start: 1101 -> 1205
ms), and a generic plan ignores parameter values.
## Tests
```bash
+6
View File
@@ -8,6 +8,12 @@ spring:
accept-float-as-int: false
jpa:
open-in-view: false
datasource:
hikari:
# Plan once, not per request: Dashboard burst 443 -> 229 ms, 94% of the DB time was planning (#49).
data-source-properties:
prepareThreshold: 1
connection-init-sql: set plan_cache_mode = force_generic_plan
flyway:
enabled: true
baseline-on-migrate: true
@@ -0,0 +1,28 @@
package core_service.configuration;
import core_service.shared.test.AbstractPersistenceTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import static org.assertj.core.api.Assertions.assertThat;
class DataSourceSettingsTest extends AbstractPersistenceTest {
@Autowired
private JdbcTemplate jdbc;
@Test
void coreConnection_ForcesGenericPlans() {
assertThat(jdbc.queryForObject("show plan_cache_mode", String.class)).isEqualTo("force_generic_plan");
}
@Test
void coreConnection_PreparesOnTheFirstUse() {
jdbc.queryForObject("select 1 where ? = 1", Integer.class, 1);
assertThat(jdbc.queryForObject(
"select count(*) from pg_prepared_statements where statement like 'select 1 where%'", Integer.class))
.isEqualTo(1);
}
}