-
Notifications
You must be signed in to change notification settings - Fork 180
Merge chunks together on compaction #397
Merge chunks together on compaction #397
Conversation
ef12bcb
to
6730dfe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this. I'm not familiar that much with the tsdb code but it looks ok to me.
compact.go
Outdated
func mergeChunks(chks []chunks.Meta) []chunks.Meta { | ||
newChks := make([]chunks.Meta, 0, len(chks)) | ||
for i := 0; i < len(chks); i++ { | ||
if i < len(chks)-1 && chks[i].Chunk.NumSamples()+chks[i+1].Chunk.NumSamples() <= 480 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be easier to read like this:
for i := 0; i < len(chks); i++ {
if i >= len(chks) - 1 || chks[i].Chunk.NumSamples()+chks[i+1].Chunk.NumSamples() > 480 {
newChks = append(newChks, chks[i])
continue
}
newChunk := chunkenc.NewXORChunk()
...
}
compact.go
Outdated
newChunk := chunkenc.NewXORChunk() | ||
app, err := newChunk.Appender() | ||
if err != nil { | ||
return chks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also log the error? Also in other places where we are returning chks
due to error.
once we clear some previous PRs I will focus on this one. Sorry for the delay. |
please remove the [WIP] when this is ready for a review. |
7968fe0
to
9d72229
Compare
@krasi-georgiev This is ready for a review now. Sorry it took awhile, the last two weeks have been a bit crazy for me. |
Also, it seems worthwhile to run prombench for this. Should I make a PR updating tsdb in Prometheus to do that? Or is there another a better way to run prombench for changes in tsdb? |
yeah for now we need a PR against Prometheus, but let me review it first and will run the tests after. |
logger log.Logger | ||
ranges []int64 | ||
chunkPool chunkenc.Pool | ||
mergeSmallChunks bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you think we should make it configurable?
What reason would we have to have it disabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly, the issue suggested that it should be an option. Also, I could imagine some queries getting slower if they look at small time ranges from long ago due to seeks taking longer. I am planning to do some additional benchmarking in that area soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok ping me when ready for another review. Thanks
Signed-off-by: Chris Marchbanks <[email protected]>
Signed-off-by: Chris Marchbanks <[email protected]>
Signed-off-by: Chris Marchbanks <[email protected]>
Signed-off-by: Chris Marchbanks <[email protected]>
Signed-off-by: Chris Marchbanks <[email protected]>
9d72229
to
0046d2d
Compare
Signed-off-by: Chris Marchbanks <[email protected]>
0046d2d
to
254d672
Compare
compact_test.go
Outdated
{ | ||
{ | ||
lset: map[string]string{"a": "b"}, | ||
chunks: [][]sample{{{t: 0}, {t: 10}}, {{t: 11}, {t: 20}}}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am also thinking that we should also test that the size of the merged chunks is as expected - doesn't pass the maxSamples boundary and not less than what is expected. This is to prevent bugs for creating too big chunks or smaller than the original once.
Probably better to add in a separate test. Maybe should also move the logic from here to the new dedicated test for merging.
also check the new chunks has the expected min/max times
4hs later 😅 and afer trying few different things this is what I came up with :
|
Signed-off-by: Chris Marchbanks <[email protected]>
I added a unit test for I am going to think a bit more on how to simplify EDIT: Ended up doing something similar to your idea, but with a couple shortcuts still in |
Signed-off-by: Chris Marchbanks <[email protected]>
441f820
to
bae6624
Compare
That sounds wrong. The compression ratio nearly reaches optimum average at about 60 samples. There's virtually no further gain at all beyond 120 samples (Figure 6). Do we have any data that would back up that bigger chunks would become more efficient? Please correct me if I misunderstood something. |
@csmarchbanks we can probably test all this roughly in a prombench test. If you open a PR against Prometheus with these changes I can start a test leave it running and test some query timings, cpu usage etc. |
@fabxc Your understanding is correct, definitely more cpu on compaction, and I don't know if it would make a real world difference. I wanted to get this in an ok enough place where it would make sense to test using prombench/a custom build of prometheus for a more realistic scenario, and verify if there are any noticeable improvements. If not, then I will close this PR because the complexity and extra cpu on compaction is definitely not worth it. I will look into some allocation optimizations as well. That sounds like an interesting path to pursue. @krasi-georgiev I will let you know when I make a prometheus PR. Should be sometime today. |
Looking at the benchmarks in prometheus/prometheus#4768, I don't think making bigger chunks is worthwhile. Query performance does not change much, and some compactions are taking much much longer (40 minutes vs 10 minutes). An alternative could be to merge tiny chunks (say less than 40 samples) into another chunk to increase compression a bit. However, in my prometheus no more than 1% of chunks would be merged, so I doubt the extra complexity is worthwhile. |
Not worth it |
fixes: #236
This is a first pass at merging small chunks together into larger ones. Initial query benchmark results seem promising for when blocks become larger. This code currently takes the 120 samples per 2 hours plan used in the head and makes the chunk size proportionally larger as the block size increases.
benchcmp results between first and last commits: