Index maintenance · Part 3 of 3

When the index grows without maintenance

Why a stable page density does not mean a quiet index – and how to compare the cost of intervening with the cost of waiting.

8 October 2026 · approx. 10 minutes

Plateau SQL Server 2022Empty-start control 2022/2025Grown to 3.6 million rowsPlay along 10 questions ↓

The findings in 30 seconds

  1. Without maintenance, the average page density settled around 68% in our test, for both starting states tested.
  2. That is not a state of rest: on the plateau, around 225 split log records per 10,000 inserts kept occurring.
  3. Waiting costs space: after 60 simulated days, the unmaintained index occupied 24% more leaf pages than one with early REBUILD. Intervening costs too; which calculation works out is decided by the workload.
  4. With ascending keys, the reserve created by a REBUILD does not help freshly appended rows if they grow later.

Waiting is a strategy, too

One possible maintenance strategy is not to intervene at all, at least at first. What happens then under continued, randomly distributed inserts? In our tests, the average page density settles while further split log records keep occurring. That leads to the practical question: is this state acceptable for your own workload, or is a targeted intervention worth it?

This is part 3 of a series. Part 1 explains pages, splits and reserve with pictures. Part 2 compares REORGANIZE and REBUILD from the same starting state.

The setup

A GUID as the clustering key plus 100 bytes of payload, 123 bytes per row. The keys come from a reproducible, widely spread hash sequence.

  • Two dense starts: 100,000 rows, built once with fill factor 100 and once with fill factor 81. Then the same randomly distributed inserts, one at a time, with no index or statistics maintenance at all. Measured after every step: page density across all leaf pages, fragmentation, split log records (LOP_DELETE_SPLIT, as explained in part 2).
  • Plateau criterion, defined in advance: over the last million inserted rows, density varies by at most one percentage point and rises or falls by at most 0.5 percentage points per million. We let the index grow to at least 3.1 million rows and then until this holds for at least eleven measurement points.
  • Cross-check: the unmaintained runs from part 2, started empty, on SQL Server 2022 and 2025.

The dense starts ran on SQL Server 2022 only, the cross-check on both versions.

The plateau

Chart 1

Page density comes to rest, the split log records keep coming

Two dense starts with 100,000 rows, then only randomly distributed single-row inserts. SQL Server 2022.

Start FF100Start FF81SQL Server 2022, no maintenance at allPage density across all leaf pages (axis from 50%)Plateau window FF100Plateau window FF8150%60%70%80%90%100%Reference empty start 2022/2025: 68.24%, not a limit98.8% at start (FF100)54.0% after 10,000 inserts81.8% at start (FF81)68.48%68.20%00.511.522.533.5Split log records per 10,000 new rows (full scale)04008001,2001,6001,593 in the first step (FF100)00.511.522.533.5Rows in the index (millions)Plateau detail: from 1 million rows, own axesPlateau window FF100Plateau window FF8166%67%68%69%70%Split log records per 10,000 (axis to 300)0100200300Plateau: 226.4 (FF100) and 223.1 (FF81)11.522.533.5 Start FF100Start FF81SQL Server 2022, no maintenance at allPage density across all leaf pagesaxis from 50%FF100FF8150%75%100%Empty start 2022/2025: 68.24%98.8% at start (FF100)54.0% after 10,000 inserts81.8% at start (FF81)68.48%68.20%0123Split log records per 10,000new rows (full scale)08001,6001,593 in the first step (FF100)0123Rows in the index (millions)Plateau detail:from 1 million rows, own axesFF100FF8166%68%70%Split log records per 10,000 (axis to 300)0100200300Plateau: 226.4 (FF100) and 223.1 (FF81)123
Top: the average page density after each measurement step; below it, the split log records of the step per 10,000 new rows (full scale to 1,600; the first step after start FF100 is at 1,593). The detail view shows the range from 1 million rows with its own axes; above each start, the plateau window (last million rows). One deterministic trajectory per start, SQL Server 2022. Dashed reference: final value of the empty-started runs from part 2 (SQL Server 2022 and 2025). The plateau is an observation within this test window, not a limit and not a maintenance target. Source: Our own measurement, LAB-12 plateau cross-check, SQL Server 2022, 6 October 2026; empty-start control SQL Server 2022/2025, 5 October 2026
Data for the chart
Rows (millions)FF100 densityFF100 split log records per 10,000FF81 densityFF81 split log records per 10,000
0.1098.78%–81.82%–
0.1153.96%1,59389.20%22
0.1258.70%971.28%696
0.1363.59%058.27%846
0.1468.48%058.06%282
0.1573.12%1161.23%60
0.1677.05%3965.09%13
0.1778.30%14668.94%12.0
0.1876.22%29972.57%22
0.1972.04%42775.37%63
0.2067.30%51576.77%130
0.2164.36%44976.37%229
0.2262.66%38574.58%309
0.2362.00%30971.34%424
0.2462.36%21468.16%459.0
0.2563.40%14665.68%440
0.2664.69%119.064.12%384.0
0.2766.37%7763.20%339
0.2868.10%6863.07%260
0.2969.82%6863.32%216
0.3071.18%96.063.92%175.0
0.4067.83%260.472.45%129
0.5065.63%266.567.23%296.5
0.6069.86%150.865.75%261.8
0.7070.20%215.068.93%159.8
0.8067.84%281.670.12%195.2
0.9066.56%267.369.09%250.2
1.0066.81%224.767.50%276.4
1.1068.13%182.766.86%253.5
1.2069.06%191.967.05%224.9
1.3069.53%204.367.70%201.8
1.4069.31%23468.69%184.4
1.5068.72%251.669.23%198.8
1.6068.12%256.969.26%222.6
1.7067.63%254.768.95%241.2
1.8067.33%247.668.56%247.1
1.9067.34%23068.21%248
2.0067.61%211.467.90%247.4
2.1067.83%214.667.68%243.7
2.2068.09%210.567.54%239.6
2.3068.38%204.767.56%227.6
2.4068.74%198.167.73%214.8
2.5068.97%208.967.90%215.8
2.6068.99%222.868.09%213.3
2.7068.97%225.668.32%206.9
2.8068.91%230.368.51%208.7
2.9068.79%236.568.65%213.6
3.0068.53%250.968.70%221.9
3.1068.37%24268.76%220.4
3.2068.20%244.368.70%230.5
3.30––68.69%226.1
3.40––68.65%230.8
3.50––68.65%226.2
3.60––68.48%245.8

First 20 steps of 10,000 inserts each, then steps of 100,000. Split log records per 10,000 = split log records of the step, converted to 10,000 new rows. Plateau window: the last million rows of each start (11 measurement points).

Page density of the two dense starts without maintenance, SQL Server 2022
StartDensity at startRows at endDensity at endDensity over the last million
FF10098.8%3.2 million68.20%68.09–68.99%
FF8181.8%3.6 million68.48%68.09–68.76%

In the first step, split activity on the densely built index is especially high; density drops from 98.8% to 54.0% within the first 10,000 inserts. After that it settles. From about 1.4 million rows on, the two curves are at most a good percentage point apart; at 3.2 and 3.6 million rows, our plateau criterion over the respective last million is met. The starting state fades away.

The empty-started runs from part 2 end at 68.24% on SQL Server 2022 and 2025. That is a rounded agreement between two different experiments, not proof of precision. The 68% are an observation in this test: neither a universal limit nor a maintenance target.

The splits do not stop

A stable average sounds like rest. It is not. On the plateau, 226.4 split log records per 10,000 inserts occur after the FF100 start and 223.1 after the FF81 start. The empty-started runs show the same: 4,559 split log records in the last 200,000 rows, around 228 per 10,000.

Density and split rate answer different questions. Density describes the state: how full are the pages on average? The split rate describes the change: how much restructuring is needed to keep it that way? A stable average also does not mean that all pages are similarly full. Freshly split, half-full pages and nearly full pages balance out on average. The average stands still because the restructuring continues at an even pace.

Waiting versus intervening

Without maintenance, there is no maintenance cost. Instead, the index pays in two other places: with recurring splits for some of the inserts and with more leaf pages.

Chart 2

After 60 days without maintenance: more leaf pages and more split log records

600,000 rows, 10,000 inserts per day, SQL 2022 and 2025 identical.

Leaf pages at the end of the lab test+24%more without maintenanceNo maintenance13,574Early REBUILD FF8010,962Cumulative split log records3.2×as many without maintenanceNo maintenance13,631Early REBUILD FF804,199Cross-check: maintenance effort of the REBUILD strategy (SQL 2022, offline under SIMPLE)Early REBUILD FF80: 20 REBUILDs, 4.4 s, 4.3 MiB log · No maintenance: no maintenance effort Leaf pages at the end of the lab test+24%more without maintenanceNo maintenance13,574Early REBUILD FF8010,962Cumulative split log records3.2×as many without maintenanceNo maintenance13,631Early REBUILD FF804,199Cross-check: maintenance effortof the REBUILD strategy (SQL 2022, offline)20 REBUILDs, 4.4 s, 4.3 MiB logNo maintenance: no maintenance effort
Gray: no maintenance. Blue: early REBUILD with fill factor 80 (from 1% fragmentation). Same scale in both pairs; units: leaf pages at the end of the lab test and cumulative split log records over 60 simulated days. Below it, the maintenance effort of the REBUILD strategy. We did not measure read times; 24% more pages do not translate into 24% slower queries. Source: Our own measurement, LAB-12, SQL Server 2022/2025, 5 October 2026
Data for the chart
StrategyLeaf pages 2022Leaf pages 2025Density at endSplit log records 2022Split log records 2025REBUILD / REORGANIZE
No maintenance13,57413,57468.2%13,63113,6310 / 0
Early REBUILD FF8010,96210,96284.5%4,1994,19920 / 0

Day 60 after 600,000 single-row inserts, empty start, GUID plus 100 bytes. The last REBUILD ran on day 57; the density of the REBUILD index is the state 3 days later.

No maintenance versus early REBUILD after 60 simulated days
Strategy (60 days)Leaf pages at endDensity at endSplit log recordsMaintenance effort (SQL 2022)
No maintenance13,57468.2%13,631–
Early REBUILD FF8010,96284.5%4,19920 REBUILDs, 4.4 s, 4.3 MiB log

At the end of the test, the unmaintained index occupies 24% more leaf pages and has produced a good three times as many split log records. A scan over the same data has to touch more leaf pages at lower density; pages already in the buffer pool do not cause another read from disk. For point lookups, the page count hardly matters. So 24% more pages do not translate into 24% slower queries; we did not measure read times here.

The cross-check is part of the picture: the REBUILD strategy needed 20 interventions. Our maintenance figures apply to this synthetic single index, offline under SIMPLE, measured as generated log record bytes. An online REBUILD writes considerably more log (part 2: 34 instead of 1.6 MiB in the frozen comparison), and an offline REBUILD can block access to the table for its duration. For a large production index, these costs shift considerably. No routine maintenance can therefore be the better overall decision.

When intervening can pay off

For an index with randomly distributed inserts, the question “wait or intervene?” comes down to four points:

  • How write-heavy is it? The more inserts into existing ranges, the more the recurring splits count.
  • How is it read? Many scans over large ranges benefit from higher density; point lookups hardly.
  • What does the intervention cost? Index size, recovery model, online or offline operation, maintenance window.
  • What does the measurement show? The same workload before and after a trial intervention, including the time until the next one.

Deep dive: A year with reserve

How often does an early REBUILD have to run? We extended the reserve strategy over 365 simulated days, 10,000 inserts every day, REBUILD as soon as fragmentation exceeds 1%. A simulated day is a fixed number of inserts, not a calendar day.

Chart 3

The gaps between two REBUILDs get longer as the index grows

Early REBUILD with fill factor 70 and 80, 365 simulated days, SQL 2022. SQL 2025 identical.

Fill factor 70Fill factor 80open at year endDays since the previous REBUILD (10,000 inserts per day)0102030405060060120180240300365open: 9 days58 days, day 298–356open: 24 days32 days, day 309–341Simulated day of the REBUILD Fill factor 70Fill factor 80open at year endDays since the previous REBUILD(10,000 inserts per day)02040600120240365open: 958 daysopen: 2432 daysSimulated day of the REBUILD
Each point is a REBUILD: horizontal the simulated day on which it ran, vertical the days since the previous REBUILD (10,000 inserts per day). Hollow diamonds without a line: the interval still open at year end, not a completed value. REBUILD from 1% fragmentation, offline under SIMPLE. A simulated day is a quantity of inserts, not a calendar plan. Source: Our own measurement, LAB-12, SQL Server 2022/2025, 5 October 2026
Data for the chart
REBUILD no.FF70 dayFF70 gapFF80 dayFF80 gap
15first5first
26161
38271
410281
512291
6153101
7183122
8224142
9275162
10336182
11407202
12488233
135810263
147012293
158414334
1610117374
1712120414
1814625465
1917428515
2020834576
2124941636
2229849707
2335658777
24––858
25––949
26––10410
27––11511
28––12712
29––14013
30––15515
31––17116
32––18918
33––20819
34––23022
35––25424
36––28026
37––30929
38––34132
Year end365open: 9365open: 24

The first REBUILD ran on day 5 in both runs, as soon as the index exceeded 1,000 leaf pages and fragmentation was above 1%. Gap = days since the previous REBUILD. SQL Server 2025: the same REBUILD days.

Early REBUILD over 365 simulated days, fill factor 70 and 80
Fill factorREBUILDs per yearLongest completed intervalSplit log recordsMaintenance total (SQL 2022)Leaf pages at end
702358 days5,32719.5 s · 19.8 MiB77,392
803832 days8,80529.8 s · 29.4 MiB65,592

The intervals get longer over time. The same number of rows arrives every day, but the index grows. The same 10,000 rows spread across more and more pages, and the reserve on each page lasts longer. An interval from the end of the year therefore says nothing about a young or small index, and it is not a calendar plan.

Split log records also occur between two REBUILDs, just few of them: in the longest FF70 interval, from day 298 to day 356, 539 accumulated over 580,000 new rows. Extrapolated with the plateau rate, it would have been around 13,000 without maintenance; that is an extrapolation, not a separate control run for this interval.

FF70 needed fewer interventions than FF80 and produced fewer split log records, but occupied 18% more pages at the end of the year. This end state also depends on how long ago the last REBUILD ran in each case. Which value is better depends on what is more expensive: writing or reading.

Growing rows with ascending keys

With IDENTITY or NEWSEQUENTIALID, new rows land at the end of the index in the simple case. New pages are appended there and filled completely. The fill factor of an earlier REBUILD has no effect on these new pages: it only applied to the pages that existed at the time of the REBUILD.

This becomes visible when rows grow after being inserted. We built 90,000 rows with FF70 or FF100, appended 10,000 and then enlarged 333 of the newly appended rows by 100 bytes each.

Chart 4

Growing updates on new pages: the same split log records at FF70 and FF100

Per key type and fill factor, median of three runs, SQL 2022 and 2025 identical.

…Updates only hereExisting pages after REBUILD(FF70: with reserve)newly appended(filled completely)Appending 10,000 rows333 growing updatesUpdates only in the newly appended range.050100150IDENTITYFill factor 701145IDENTITYFill factor 1000145NEWSEQUENTIALIDFill factor 700162NEWSEQUENTIALIDFill factor 1000162Split log records (LOP_DELETE_SPLIT) Appending 10,000 rows333 growing updatesUpdates only in the newlyappended range.…Updates only hereExisting pages after REBUILD(FF70: with reserve)newly appended(filled completely)050100150IDENTITY · FF701145IDENTITY · FF1000145NEWSEQUENTIALID · FF700162NEWSEQUENTIALID · FF1000162Split log records (LOP_DELETE_SPLIT)
Updates only in the newly appended range. Gray: 10,000 rows appended at the end of the index. Orange: then 333 of these new rows enlarged by 100 bytes each. Unit: split log records (LOP_DELETE_SPLIT); the values 0 and 1 are labeled as numbers. This test says nothing about updates on older pages that existed at the time of the REBUILD. Source: Our own measurement, LAB-12, SQL Server 2022/2025, 5 October 2026
Data for the chart
KeyFill factorPages beforeafter appendingafter updatesDensity after appendingSplit log records appendingSplit log records updates
IDENTITY701,8371,9822,12772.9%1145
IDENTITY1001,3051,4501,59599.7%0145
NEWSEQUENTIALID702,0462,2072,36872.2%0162
NEWSEQUENTIALID1001,4521,6131,77398.8%0162

Median of three runs; all three runs and both versions deliver the same numbers. The new pages at the end of the index are filled completely, regardless of the fill factor of the existing pages.

Split log records when appending and during 333 growing updates in the newly appended range
KeyFill factorSplit log records when appendingSplit log records during 333 updates
IDENTITY701145
IDENTITY1000145
NEWSEQUENTIALID700162
NEWSEQUENTIALID1000162

In this test, only freshly appended rows grow. The reserve created by the REBUILD in the older range does not help them: FF70 and FF100 produce the same numbers. If, on the other hand, rows on the freshly rebuilt pages grow, the free space there can matter; we did not measure that here. For the decision, you therefore have to check where and by how much rows grow. Hotspots at the end of the index under many concurrent writers and the behavior of NEWSEQUENTIALID after restarts are outside the scope of this test.

Deep dive: Why about two thirds?

A split leaves behind two roughly half-full pages. They then fill up until they are full again and split again. With randomly distributed inserts, the pages are therefore spread across many fill levels, and the average is well below “full”. Andrew Yao's analysis of randomly growing B-trees of high order offers a theoretical orientation for this with ln 2 ≈ 69% (Acta Informatica 9, 1978). SQL Server pages with whole rows, overhead and concrete split behavior are not equated with that. That our observation lies in the same region is an orientation, not a derivation.

What this means for maintenance

The state without maintenance is neither a target nor a threshold. It shows where an index with randomly distributed inserts goes without intervention: about two thirds full on average, with splits continuing at an even pace. Whether that is a problem is decided by the workload.

The guiding principle of this series:

Index maintenance needs a measurable goal. What matters is whether its effect on the workload justifies the cost and the disruption to operations.

For the patterns from this series, as a starting point for your own check:

Pattern, behavior without maintenance and candidate to test
PatternWhat happens without maintenanceCandidate to test
Randomly distributed inserts, write-heavyPlateau around two thirds density, splits continueREBUILD with reserve; measure interval and fill factor
Randomly distributed inserts, read-heavy with many scansMore leaf pages for every scanREBUILD with a higher fill factor, less often
Ascending keys, rows stay unchangedPages are appended fullhardly any routine physical maintenance
Ascending keys, freshly inserted rows growSplits on the new pages at the endcheck the data model, row growth and its timing
Growing updates on older rowsSplits in the existing rangeadditionally check local reserve and fill factor
Hardly any changesnothingno routine physical maintenance; update statistics only when there is a proven need

No row of this table is a rule. Each is a hypothesis to be measured against your own workload, before and after.

Origins and further work

The experiment ideas and cross-checks in this series build in particular on Jeff Moden's work on index maintenance. In his talk “Black Arts” Index Maintenance #1, he places a year-long simulation without maintenance next to several maintenance strategies and gives an average page density of 68.24% for the unmaintained curve. He calls this comparison curve without maintenance the “Brent Line”, after Brent Ozar; it is a reference curve, not a SQL Server feature and not a maintenance threshold. He has used the name since at least 2020 on SQLServerCentral. He suggested the test with a densely built start to us in our exchange on LinkedIn. He makes slides and scripts freely available for learning purposes. We thank him for the suggestions. Our measurements come from the PSG lab; their conditions and limits are stated in each case.

Limits of the measurement
  • Synthetic data, one clustered index without nonclustered indexes, fixed row width, no deletes, no compression, no partitions.
  • One deterministic trajectory per starting state; no measure of spread across different random sequences. The plateau is a limited observation according to our criterion, not proof of a permanent limit.
  • The dense starts ran on SQL Server 2022 (16.0.4295.3) only; the empty-started controls and the year-long runs on 2022 and 2025 (17.0.5005.3). Maintenance times and log volumes in the tables are SQL 2022 values; on 2025 they differ slightly, while pages, split log records and intervals are identical.
  • Serial load, MAXDOP 1, no concurrent writers. Maintenance offline under SIMPLE; locking impact and online costs in the year-long run not measured.
  • Read costs derived from the page count only; we did not measure scans or read times.
  • A simulated day is a quantity of inserts, not a calendar forecast.
  • Checked on 5 and 6 October 2026. The test conditions are documented; we will provide separate information about a public reproduction package.
Quiz · 10 questions

What does your index do when nobody maintains it?

Every answer is explained right away, with a link to the relevant part of the article. At the end, you get an assessment and a link you can share. No cookies.

Further reading