Evaluate a change without optimizing for one execution

An alternative is not validated merely because one execution finishes quickly. It must preserve the result, repeat the benefit with different parameters, and show which aspects improve, which remain unchanged, and which have not yet been tested.

Recover the hypothesis

The previous entry observed 482 logical reads and an Index Scan that examined 100,000 rows to return 136. The provisional explanation pointed to the functions applied to FechaPedido:

WHERE YEAR(p.FechaPedido) = YEAR(@TargetDate)
  AND MONTH(p.FechaPedido) = MONTH(@TargetDate)
  AND DAY(p.FechaPedido) = DAY(@TargetDate)

The alternative expresses the same day as a range:

WHERE p.FechaPedido >= @TargetDate
  AND p.FechaPedido < DATEADD(DAY, 1, @TargetDate)

The prediction is testable: the range must preserve counts and amounts while reducing read work. If either result is absent, the hypothesis loses support.

Choose parameters before measuring

The table contains 730 distinct dates. To prevent one date from deciding the conclusion, the test selects three positions from the available interval:

Position Date Rows
Beginning 2024-01-01 137
Middle 2024-12-30 137
End 2025-12-30 136

These dates test whether the behavior repeats at separated points. They do not represent a skewed distribution: all three days contain similar volumes. A workload with empty days, month-end activity, or exceptional concentrations would need additional parameters.

Prove equivalence before comparing performance

Both variants are grouped by date and status. The check preserves counts and amounts separately:

Equal counts and amounts for the three tested dates

  1. 1
    Same result

    The function and range columns match across all six compared groups.

The equality includes times stored within each day. The lower boundary includes the beginning of the date and the upper boundary excludes the beginning of the next day; it does not require FechaPedido to end at midnight.

Separate warm-up from measurement

Each variant runs once per date with a warm-up label. A different series then begins with text that can be identified in the cache:

/* PE29_FUNCTIONS_MEASURED_20261030 */
SELECT
    p.Estado,
    COUNT_BIG(*) AS Orders,
    SUM(p.Total) AS TotalAmount
FROM dbo.PedidoLaboratorio AS p
WHERE YEAR(p.FechaPedido) = YEAR(@TargetDate)
  AND MONTH(p.FechaPedido) = MONTH(@TargetDate)
  AND DAY(p.FechaPedido) = DAY(@TargetDate)
GROUP BY p.Estado
ORDER BY TotalAmount DESC;
/* PE29_RANGE_MEASURED_20261030 */
SELECT
    p.Estado,
    COUNT_BIG(*) AS Orders,
    SUM(p.Total) AS TotalAmount
FROM dbo.PedidoLaboratorio AS p
WHERE p.FechaPedido >= @TargetDate
  AND p.FechaPedido < DATEADD(DAY, 1, @TargetDate)
GROUP BY p.Estado
ORDER BY TotalAmount DESC;

The test alternates both queries five times for each date. This produces 15 measured executions per variant without running one full series before the other.

Alternation does not remove activity on the machine or turn the test into a production benchmark. It avoids a basic ordering difference and shows whether reads remain consistent within each variant.

Compare repeated work

Accumulated logical reads for fifteen executions per variant

  1. 1
    Functions

    All 15 executions record 482 logical reads: minimum, maximum, and average remain at 482.

  2. 2
    Range

    The 15 executions record between 2 and 4 logical reads, with an average of 2.67.

The repetition supports the prediction for these three dates. It does not prove that every date query will produce the same difference: index size, distribution, and requested interval can change the work.

Read timings as an observed distribution

CPU, elapsed time, and cached plans for the measured variants

  1. 1
    Functions

    The observed averages were 30.326 ms of CPU and 30.329 ms elapsed.

  2. 2
    Range

    The observed averages were 0.432 ms of CPU and 0.433 ms elapsed.

sys.dm_exec_query_stats accumulated the 15 executions and showed one cached plan for each measured text. This describes the test window. It does not guarantee that the same plan will remain stable after restarts, statistics changes, recompilations, or parameters with a different distribution.

The timings accompany the read evidence, but they are not turned into a commercial improvement percentage. They depend too heavily on this machine and controlled workload to be transferred without another measurement.

Compare the actual plans

The function variant preserves the traversal observed in the hypothesis:

Actual plan for the function variant with an Index Scan

  1. 1
    Index Scan

    The operator traverses the date index and applies the predicate to the rows it examines.

The range enables a different access method:

Actual plan for the half-open range with an Index Seek

  1. 1
    Index Seek

    The boundaries form a range on the FechaPedido key.

Hash Match (Aggregate) and Sort remain because the query still groups and orders. The change addresses row access; it does not remove the work required to form the result.

Verify rows read and one remaining signal

Index Seek properties with 136 rows read and returned

  1. 1
    Rows returned

    The operator returns the 136 rows from the final date.

  2. 2
    Rows read

    The operator reads those same 136 rows instead of examining all 100,000 rows in the structure.

The representative range plan estimated 16,432 rows and observed 136. The access method improved, but the estimate did not become aligned. A correction does not have to resolve every signal in the plan to be useful, and it should not hide the signals that remain.

In this query the date is declared in a local variable. That form can limit the information available during compilation. The estimate deserves a separate test using the way the application actually sends the parameter before assigning it a definitive cause.

Review effects outside the measurement

  • Different parameters: three separated dates preserved results and the read difference; extreme distributions remain untested.
  • Writes: the change modifies the predicate and adds no maintenance to INSERT, UPDATE, or DELETE.
  • Storage: no additional index was created, so structure space is unchanged.
  • Other plans: the test covers this text. It does not show how other queries on FechaPedido will react.
  • Blocking: there was no concurrent load. Reading fewer pages may reduce work, but this test did not measure waits or lock duration.
  • Stability: one plan per variant was cached during the series; this is not long-term stability evidence.

Decide with the correct scope

The hypothesis receives support within the test: the range preserves results, changes access from Scan to Seek, and reduces reads across all 15 measured executions. It can advance as a candidate modification for this query.

Before applying it in another system, the actual application text, parameters representative of its distribution, concurrency, current statistics, and the complete workload still need to be tested. A conclusion is more useful when it also states what it does not know.

Next reasonable check

The next entry will bring the complete method together in a reproducible business case: context, baseline, plan, metrics, hypothesis, change, new measurement, and a conclusion limited by the evidence.

Path index

Execution plans

30 articles in Execution plans
  1. 01What an execution plan is for
  2. 02Estimated plans, actual plans, and Live Query Statistics
  3. 03How an execution plan tree is organized
  4. 04Arrows, properties, and execution counts
  5. 05Operator map: what role each node plays
  6. 06Estimated rows and actual rows
  7. 07Index Seek, Index Scan, and Table Scan
  8. 08Key Lookup and repeated work
  9. 09Filter, Compute Scalar, and Top
  10. 10Nested Loops, Hash Match, and Merge Join
  11. 11Sort, Segment, and Sequence Project
  12. 12Stream Aggregate and Hash Match Aggregate
  13. 13Spool: materialization and reuse
  14. 14Parallelism: distributing, repartitioning, and gathering rows
  15. 15Execution plan warnings that require investigation
  16. 16Actions available in the SSMS graphical plan
  17. 17How Showplan XML is organized
  18. 18Walk through Analyze Actual Execution Plan
  19. 19Reads with SET STATISTICS IO
  20. 20CPU and elapsed time with SET STATISTICS TIME
  21. 21Build a repeatable baseline
  22. 22Save and compare two plans
  23. 23History and regressions with Query Store
  24. 24Turn an Analyze Actual Execution Plan scenario into a hypothesis
  25. 25Read a Missing Index suggestion in an execution plan
  26. 26Understand the CREATE INDEX generated by SSMS
  27. 27Decide, create, and verify an index
  28. 28From a slow query to a testable hypothesis
  29. 29Evaluate a change without optimizing for one execution
  30. 30Guided analysis of a reproducible business query