Skip to content

feat: Logging and fsync delay for retention deletion#27114

Merged
devanbenz merged 30 commits intomaster-1.xfrom
db/retention-hanging
Jan 16, 2026
Merged

feat: Logging and fsync delay for retention deletion#27114
devanbenz merged 30 commits intomaster-1.xfrom
db/retention-hanging

Conversation

@devanbenz
Copy link
Copy Markdown

@devanbenz devanbenz commented Jan 13, 2026

This area of the code is where we "hang" during retention policy deletion. It only occurs in very high cardinality dbs ~10 million+. DeleteSeriesID holds a mutex lock and does a fsync call. Running this millions of times + contention + disk I/O between various other writers/readers this could potentially go on for days.

Notes on changes:

After running influxdb with inch running in the background I see the following

ts=2026-01-13T22:19:09.734212Z lvl=warn msg="Average elapsed time for each deletion" log_id=10QLBhBl000 avg=7.677ms

That's ~7.5ms per DeleteSeriesID call.

So for ~35 million cardinality it should take approximately ~3 days to run. I would expect it to take longer due to lock contention + higher resource utilization. I also had far less cardinality.

It does appear like the fsync is killing performance

ts=2026-01-14T21:11:19.477584Z lvl=info msg="Average elapsed time for each series deletion" log_id=10Ra89D0000 avg=0.000ms

The time is so little I need to adjust my calculations

ts=2026-01-14T21:11:19.292908Z lvl=info msg="DeleteShard: 10000 series deleted" log_id=10Ra89D0000 service=store db=retention_slow shard_id=67 deleted=10001 remaining=489899 total=499900 elapsed=2.380ms

~2ms for 10k series vs previously it was ~7ms for a single series.

This PR also adds a log to trigger every 10k series when we're looping through and deleting series for better debugging.

I suspect this area of the code is where we "hang" during
retention policy deletion. It only occurs in very high cardinality
dbs ~10 million+. `DeleteSeriesID` holds a mutex lock and does a fsync
call. Running this millions of times + contention + disk I/O between various
other writers/readers this could potentially go on for days.

This PR adds a WARN log to trigger every 24 hours when we're looping through
and deleting series.
@devanbenz devanbenz changed the title feat: Adds WARN log if series deletion takes longer than 24h feat: Adds log per 10k series during shard deletion Jan 14, 2026
@devanbenz devanbenz marked this pull request as ready for review January 14, 2026 18:46
Copy link
Copy Markdown
Contributor

@davidby-influx davidby-influx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think extracting the call to Flush and making DeleteSeriesID take an iterable construct would be worth testing. The only place it is called outside of a loop is in a test, which could easily be changed to a single element array.

@devanbenz devanbenz changed the title feat: Adds log per 10k series during shard deletion feat: Logging and fsync delay for retention deletion Jan 14, 2026
@devanbenz devanbenz marked this pull request as draft January 14, 2026 23:25
Copy link
Copy Markdown
Member

@gwossum gwossum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few minor questions, but overall nice job on finding this performance bottleneck!

@davidby-influx
Copy link
Copy Markdown
Contributor

@devanbenz - Please create port issues for this in main-2.x and RR. Add to the epic issue, as well: OSS 2.9.0 cherry-picks

Copy link
Copy Markdown
Contributor

@davidby-influx davidby-influx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great start!

@davidby-influx
Copy link
Copy Markdown
Contributor

My thoughts was to have SeriesFile.DeleteSeriesID take a list/iterable of IDs and move the looping into it. All the places it is called are loops except one test, which could become a single element slice.

@devanbenz
Copy link
Copy Markdown
Author

devanbenz commented Jan 15, 2026

My thoughts was to have SeriesFile.DeleteSeriesID take a list/iterable of IDs and move the looping into it. All the places it is called are loops except one test, which could become a single element slice.

I created a DeleteSeries method which just takes in an iterable and a function. Not sure if I like this better than ss.ForEach.

I kind of think we should keep the code as is since it's been using ForEach for many years. I'm tempted to not try and change the code too much and just move around the flush semantics. I think having DeleteSeriesID as an atomic operation is fine, if I wanted to throw the iterable inside the deletion I would probably implement a DeleteManySeries function or something and give it a slice of IDs or the SeriesIDSet.

@devanbenz devanbenz marked this pull request as ready for review January 15, 2026 21:57
Copy link
Copy Markdown
Contributor

@davidby-influx davidby-influx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a big opportunity for another optimization here....

@davidby-influx
Copy link
Copy Markdown
Contributor

Please add to the 2.9.0 epic if you haven't yet.

Copy link
Copy Markdown
Contributor

@davidby-influx davidby-influx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting faster!

pre-allocate slices
add a constant for SeriesN in segment flush tests
check error returns in tests
Copy link
Copy Markdown
Contributor

@davidby-influx davidby-influx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Nice work, should give us a big speed-up for high-cardinality databases.

@devanbenz devanbenz merged commit c836ac2 into master-1.x Jan 16, 2026
9 checks passed
@devanbenz devanbenz deleted the db/retention-hanging branch January 16, 2026 22:24
devanbenz added a commit that referenced this pull request Jan 16, 2026
This area of the code is where we "hang" during retention policy deletion. It only occurs in very high cardinality dbs ~10 million+. DeleteSeriesID holds a mutex lock and does a fsync call. Running this millions of times + contention + disk I/O between various other writers/readers this could potentially go on for days.

This PR batches sync operations instead of running a sync during every series deletion op. It also adds additional logging to retention series deletion.

(cherry picked from commit c836ac2)
devanbenz added a commit that referenced this pull request Feb 17, 2026
This area of the code is where we "hang" during retention policy deletion. It only occurs in very high cardinality dbs ~10 million+. DeleteSeriesID holds a mutex lock and does a fsync call. Running this millions of times + contention + disk I/O between various other writers/readers this could potentially go on for days.

This PR batches sync operations instead of running a sync during every series deletion op. It also adds additional logging to retention series deletion.

(cherry picked from commit c836ac2)
devanbenz added a commit that referenced this pull request Feb 18, 2026
* feat: Logging and fsync delay for retention deletion (#27114)

This area of the code is where we "hang" during retention policy deletion. It only occurs in very high cardinality dbs ~10 million+. DeleteSeriesID holds a mutex lock and does a fsync call. Running this millions of times + contention + disk I/O between various other writers/readers this could potentially go on for days.

This PR batches sync operations instead of running a sync during every series deletion op. It also adds additional logging to retention series deletion.

(cherry picked from commit c836ac2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants