From 1cc02930b621d85d1bb548a65c3c8b079e67b2ec Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Wed, 14 Oct 2020 11:06:17 +0200 Subject: [PATCH] Implement series API query hint to not hit chunks (#8050) Fixes https://github.com/prometheus/prometheus/issues/5547 Signed-off-by: Goutham Veeramachaneni --- tsdb/querier.go | 29 ++++++++++++++++++++++++----- web/api/v1/api.go | 8 +++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/tsdb/querier.go b/tsdb/querier.go index 8bde49a4b..6df8cba9b 100644 --- a/tsdb/querier.go +++ b/tsdb/querier.go @@ -120,11 +120,6 @@ func NewBlockQuerier(b BlockReader, mint, maxt int64) (storage.Querier, error) { func (q *blockQuerier) Select(sortSeries bool, hints *storage.SelectHints, ms ...*labels.Matcher) storage.SeriesSet { mint := q.mint maxt := q.maxt - if hints != nil { - mint = hints.Start - maxt = hints.End - } - p, err := PostingsForMatchers(q.index, ms...) if err != nil { return storage.ErrSeriesSet(err) @@ -132,6 +127,16 @@ func (q *blockQuerier) Select(sortSeries bool, hints *storage.SelectHints, ms .. if sortSeries { p = q.index.SortedPostings(p) } + + if hints != nil { + mint = hints.Start + maxt = hints.End + if hints.Func == "series" { + // When you're only looking up metadata (for example series API), you don't need to load any chunks. + return newBlockSeriesSet(q.index, newNopChunkReader(), q.tombstones, p, mint, maxt) + } + } + return newBlockSeriesSet(q.index, q.chunks, q.tombstones, p, mint, maxt) } @@ -821,3 +826,17 @@ Outer: } func (it *deletedIterator) Err() error { return it.it.Err() } + +type nopChunkReader struct { + emptyChunk chunkenc.Chunk +} + +func newNopChunkReader() ChunkReader { + return nopChunkReader{ + emptyChunk: chunkenc.NewXORChunk(), + } +} + +func (cr nopChunkReader) Chunk(ref uint64) (chunkenc.Chunk, error) { return cr.emptyChunk, nil } + +func (cr nopChunkReader) Close() error { return nil } diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 0c7a86d87..284278e52 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -602,10 +602,16 @@ func (api *API) series(r *http.Request) (result apiFuncResult) { q.Close() } + hints := &storage.SelectHints{ + Start: timestamp.FromTime(start), + End: timestamp.FromTime(end), + Func: "series", // There is no series function, this token is used for lookups that don't need samples. + } + var sets []storage.SeriesSet for _, mset := range matcherSets { // We need to sort this select results to merge (deduplicate) the series sets later. - s := q.Select(true, nil, mset...) + s := q.Select(true, hints, mset...) sets = append(sets, s) }