From cf7f6108fde56384218570e7d145d9bddbfe2890 Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Wed, 29 Nov 2017 08:28:55 +0100 Subject: [PATCH] Order postings lists in index file by key Aligning postings list for similar keys close to each other improves page cache hit rates in typical queries that select postings for multiple label pairs with the same name. --- compact.go | 2 +- postings.go | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/compact.go b/compact.go index 35cb36a63..427731e31 100644 --- a/compact.go +++ b/compact.go @@ -589,7 +589,7 @@ func (c *LeveledCompactor) populateBlock(blocks []BlockReader, meta *BlockMeta, } } - for l := range postings.m { + for _, l := range postings.sortedKeys() { if err := indexw.WritePostings(l.Name, l.Value, postings.get(l.Name, l.Value)); err != nil { return errors.Wrap(err, "write postings") } diff --git a/postings.go b/postings.go index 63fb1e31a..1ebc7c576 100644 --- a/postings.go +++ b/postings.go @@ -50,6 +50,25 @@ func newUnorderedMemPostings() *memPostings { } } +// sortedKeys returns a list of sorted label keys of the postings. +func (p *memPostings) sortedKeys() []labels.Label { + p.mtx.RLock() + keys := make([]labels.Label, 0, len(p.m)) + + for l := range p.m { + keys = append(keys, l) + } + p.mtx.RUnlock() + + sort.Slice(keys, func(i, j int) bool { + if d := strings.Compare(keys[i].Name, keys[j].Name); d != 0 { + return d < 0 + } + return keys[i].Value < keys[j].Value + }) + return keys +} + // Postings returns an iterator over the postings list for s. func (p *memPostings) get(name, value string) Postings { p.mtx.RLock()