Skip to content

perf: replace CAT_OPTIONS correlated subselect with LATERAL JOIN in DXF2 EventQuery#23743

Open
jason-p-pickering wants to merge 2 commits into
2.40from
perf-cat-options-lateral-join-dxf2
Open

perf: replace CAT_OPTIONS correlated subselect with LATERAL JOIN in DXF2 EventQuery#23743
jason-p-pickering wants to merge 2 commits into
2.40from
perf-cat-options-lateral-join-dxf2

Conversation

@jason-p-pickering

@jason-p-pickering jason-p-pickering commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Correlated sub+selects in the SELECT list execute once per row. Moving to a LATERAL JOIN lets the planner hoist and materialise the aggregation once per COC rather than re-evaluating it for every event row. The vast majority of programs do not use an AOC, so most of the time, this is always going to be "default". The subselect was doing redundant work proportional to event count even when the answer was identical every time. LATERAL collapses that.

Testing on a production scale system reveals that the query time can be decreased from 220ms to under 70ms.

Tracker performance tests were inconclusive, but there appeared to be no regression. The difference on the production scale DB was relatively modest, even with millions of events.

Median Response Time (p50) (ms)

Scenario Baseline Feature Diff Change
Get ANC events|Go to first page 9 10 +1 ⬆️ +11.1%
Get ANC events|Search not assigned 9 10 +1 ⬆️ +11.1%
Get Child Programme TEs|Get TEs from events 7 6 -1 ⬇️ -14.3%
Get Child Programme TEs|Get TEs with enrollment status 42 41 -1 ⬇️ -2.4%
Get Child Programme TEs|Get first page of TEs 39 38 -1 ⬇️ -2.6%
Get Child Programme TEs|Not found TE by name with eq operator 12 12 +0 +0.0%
Get Child Programme TEs|Not found TE by name with like operator 13 13 +0 +0.0%
Get Child Programme TEs|Search Birth events 91 92 +1 ⬆️ +1.1%
Get Child Programme TEs|Search TE by name with eq operator 17 17 +0 +0.0%
Get Child Programme TEs|Search TE by name with like operator 21 21 +0 +0.0%
Get Child Programme TEs|Go to single enrollment|Get first enrollment 11 11 +0 +0.0%
Get Child Programme TEs|Go to single enrollment|Get first tracked entity 21 21 +0 +0.0%
Get Child Programme TEs|Go to single enrollment|Get relationships for first tracked entity 3 2 -1 ⬇️ -33.3%
Get Child Programme TEs|Go to single enrollment|Get one event|Get first event from enrollment 12 11 -1 ⬇️ -8.3%
Get Child Programme TEs|Go to single enrollment|Get one event|Get relationships for first event 2 2 +0 +0.0%
Login 71 73 +2 ⬆️ +2.8%

95th Percentile Response Time (p95) (ms)

Scenario Baseline Feature Diff Change
Get ANC events|Go to first page 12 13 +1 ⬆️ +8.3%
Get ANC events|Search not assigned 11 13 +2 ⬆️ +18.2%
Get Child Programme TEs|Get TEs from events 7 7 +0 +0.0%
Get Child Programme TEs|Get TEs with enrollment status 45 44 -1 ⬇️ -2.2%
Get Child Programme TEs|Get first page of TEs 43 41 -2 ⬇️ -4.7%
Get Child Programme TEs|Not found TE by name with eq operator 14 13 -1 ⬇️ -7.1%
Get Child Programme TEs|Not found TE by name with like operator 15 15 +0 +0.0%
Get Child Programme TEs|Search Birth events 96 98 +2 ⬆️ +2.1%
Get Child Programme TEs|Search TE by name with eq operator 21 21 +0 +0.0%
Get Child Programme TEs|Search TE by name with like operator 25 25 +0 +0.0%
Get Child Programme TEs|Go to single enrollment|Get first enrollment 12 13 +1 ⬆️ +8.3%
Get Child Programme TEs|Go to single enrollment|Get first tracked entity 23 23 +0 +0.0%
Get Child Programme TEs|Go to single enrollment|Get relationships for first tracked entity 4 3 -1 ⬇️ -25.0%
Get Child Programme TEs|Go to single enrollment|Get one event|Get first event from enrollment 13 13 +0 +0.0%
Get Child Programme TEs|Go to single enrollment|Get one event|Get relationships for first event 3 3 +0 +0.0%
Login 74 79 +5 ⬆️ +6.8%

⬇️ = faster (improvement), ⬆️ = slower (regression)

…XF2 EventQuery

Correlated subselects in the SELECT list execute once per row. Moving to
a LATERAL JOIN lets the planner hoist and materialise the aggregation once
per COC rather than re-evaluating it for every event row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

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.

1 participant