Skip to content

perf: eliminate program and program stage table joins in tracker event queries DHIS2-20922#23044

Merged
teleivo merged 1 commit intomasterfrom
DHIS2-20922-program-join
Feb 25, 2026
Merged

perf: eliminate program and program stage table joins in tracker event queries DHIS2-20922#23044
teleivo merged 1 commit intomasterfrom
DHIS2-20922-program-join

Conversation

@teleivo
Copy link
Copy Markdown
Contributor

@teleivo teleivo commented Feb 24, 2026

Eliminate program and programstage table joins from tracker event queries when the respective parameter is known. The columns (uid, code, name, attributeValues) are already available from the Java objects loaded during request validation, so we populate them directly in the row mapper instead of joining the tables.

Same approach as #22920 for tracked entities and #22972 for enrollments.

The program parameter is mandatory for /api/tracker/events, so the program join is always eliminated. The programstage join is eliminated when a specific program stage is requested.

Before:

select
    ...
    p.uid as p_uid, p.code as p_code, p.name as p_name,
    p.attributevalues as p_attributevalues,
    ps.uid as ps_uid, ps.code as ps_code, ps.name as ps_name,
    ps.attributevalues as ps_attributevalues,
    ...
    p.type as p_type,
    ...
from trackerevent ev
inner join enrollment en on en.enrollmentid = ev.enrollmentid
inner join program p on p.programid = en.programid
inner join programstage ps on ps.programstageid = ev.programstageid
...
where
    p.programid = 1150449
    and ps.programstageid in (860005, 1150450, 859998)

After (with program and program stage known):

select
    ...
    ev.eventid as ev_id, ev.status as ev_status,
    ...
from trackerevent ev
inner join enrollment en on en.enrollmentid = ev.enrollmentid
...
where
    en.programid = 1150449
    and ev.programstageid = 860005

Performance

Database

Sierra Leone DB with ~10M tracked entities, ~32M events. EXPLAIN ANALYZE (4 warmup runs) and pgbench (1 client, 30s) on the base event query (program=ur1Edk5Oe2n&pageSize=3).

Metric Baseline (all joins) No program join No program+stage joins
Planning Time 19.2 ms 16.7 ms (-13%) 18.2 ms (-5%)
pgbench TPS 57.2 65.2 (+14%) 71.7 (+25%)
pgbench latency 17.5 ms 15.3 ms (-12%) 13.9 ms (-20%)

Execution time unchanged (~11ms). The gains are in planning time and sustained throughput. With both joins eliminated, pgbench throughput improves by 25%.

@teleivo teleivo force-pushed the DHIS2-20922-program-join branch from 20ff901 to 1185734 Compare February 24, 2026 13:24
@teleivo teleivo marked this pull request as ready for review February 24, 2026 13:54
@teleivo teleivo force-pushed the DHIS2-20922-program-join branch from 1185734 to b915387 Compare February 24, 2026 13:54
When a specific program is given, the program table join is unnecessary.
The program's metadata (uid, code, name, type, attributeValues) is
already available from the Java Program object and can be populated
in the RowMapper instead of fetching from the database.

- Skip program join when enrolledInTrackerProgram is set
- Use en.programid instead of p.programid in WHERE clause
- Use ev.programstageid instead of ps.programstageid in WHERE clause
  (programstage join kept for SELECT columns only)
- Populate program fields from Java object in RowMapper

Same approach as the tracked entity store (PR #22920) and the
enrollment store (PR #22970).
@teleivo teleivo force-pushed the DHIS2-20922-program-join branch from b915387 to e987dcf Compare February 24, 2026 14:04
@teleivo teleivo changed the title perf: eliminate program table join in tracker event queries DHIS2-20922 perf: eliminate program and program stage table joins in tracker event queries DHIS2-20922 Feb 24, 2026
@teleivo teleivo requested review from ameenhere, enricocolasante and muilpp and removed request for muilpp February 24, 2026 14:05
@sonarqubecloud
Copy link
Copy Markdown

@teleivo teleivo merged commit a0ae27e into master Feb 25, 2026
16 checks passed
@teleivo teleivo deleted the DHIS2-20922-program-join branch February 25, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants