The symptom

One of the most important daily operational reports took 306 seconds to load. Five minutes is not merely slow. In an operational setting, it means people stop using the report. They call each other, keep separate lists or make decisions from memory instead.

The obvious explanation was growing data volume or insufficient server capacity. The execution plan showed something else.

What the execution plan revealed

The query consisted of logically separated building blocks, but several parts depended on the same expensive intermediate results. The execution plan showed that the database engine was not calculating these once and reusing them: identical joins, filters and aggregations were being repeated across multiple execution branches.

The source therefore looked easy to follow while the actual execution performed the same work many times. The bottleneck was not one faulty statement but the execution structure of the query as a whole.

The change

We did not touch the business rules. Instead, we separated execution into explicit phases:

  1. We calculated expensive intermediate results once and reused them through indexable structures.
  2. We moved filters to the earliest safe point.
  3. We aligned indexes with the actual join and filtering patterns.
  4. We compared the original and rewritten result sets after every change.

The most important constraint was preserving the meaning of the report. A fast query that calculates something different is not an optimisation. It is a defect.

The result

Measurement Before After
Response time 306 s 0.4 s
Improvement — 765×
Business logic original unchanged

There was no larger server, database replacement or new reporting platform. The fix came from reading the execution plan correctly and changing the structure of the query.

If your report takes five minutes to load, the server is often not the problem. The structure of the query is — and that can be fixed without replacing the system.