From 80fc80c1212702545c556417b219c31d136fc294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 22 Sep 2026 10:40:50 +0200 Subject: [PATCH] perf: index metricarchive.metricid used by the metrics archive job MetricsArchiveScheduler looks each archived row up by metricId twice: once in saveMetricsArchive (dedup) and once before deleting the source row (verify). MetricArchive declared no index on metricId, so both lookups were full scans of metricarchive and the cost of archiving a single row grew linearly with the size of the archive. Adding Index(metricId) to MetricArchive.dbIndexes makes both lookups index scans. Schemifier creates the missing index on existing deployments at boot. --- obp-api/src/main/scala/code/metrics/MappedMetrics.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala index 12288848c9..ba8be12440 100644 --- a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala +++ b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala @@ -997,7 +997,10 @@ class MetricArchive extends APIMetric with LongKeyedMapper[MetricArchive] with I override def getAuthType(): String = authType.get } object MetricArchive extends MetricArchive with LongKeyedMetaMapper[MetricArchive] { + // metricId: MetricsArchiveScheduler looks each archived row up by metricId twice (the dedup in + // saveMetricsArchive and the verify before deleting the source row). Without this index both + // lookups scan the whole archive, so the cost of archiving one row grows with the archive size. override def dbIndexes = Index(userId) :: Index(consumerId) :: Index(url) :: Index(date) :: Index(userName) :: - Index(appName) :: Index(developerEmail) :: Index(consentReferenceId) :: super.dbIndexes + Index(appName) :: Index(developerEmail) :: Index(consentReferenceId) :: Index(metricId) :: super.dbIndexes }