2017-04-26 16:01:13 +00:00
# Index Disk Format
2017-04-24 12:33:42 +00:00
The following describes the format of the `index` file found in each block directory.
2017-04-28 12:17:53 +00:00
It is terminated by a table of contents which serves as an entry point into the index.
2017-04-24 12:33:42 +00:00
```
2017-04-26 16:01:13 +00:00
┌────────────────────────────┬─────────────────────┐
2017-04-28 12:28:25 +00:00
│ magic(0xBAAAD700) < 4b > │ version(1) < 1 byte > │
2017-04-26 16:01:13 +00:00
├────────────────────────────┴─────────────────────┤
│ ┌──────────────────────────────────────────────┐ │
│ │ Symbol Table │ │
│ ├──────────────────────────────────────────────┤ │
│ │ Series │ │
│ ├──────────────────────────────────────────────┤ │
│ │ Label Index 1 │ │
│ ├──────────────────────────────────────────────┤ │
│ │ ... │ │
│ ├──────────────────────────────────────────────┤ │
│ │ Label Index N │ │
│ ├──────────────────────────────────────────────┤ │
│ │ Postings 1 │ │
│ ├──────────────────────────────────────────────┤ │
│ │ ... │ │
│ ├──────────────────────────────────────────────┤ │
│ │ Postings N │ │
│ ├──────────────────────────────────────────────┤ │
2020-10-19 08:57:19 +00:00
│ │ Label Offset Table │ │
2017-10-02 13:56:57 +00:00
│ ├──────────────────────────────────────────────┤ │
2020-10-19 08:57:19 +00:00
│ │ Postings Offset Table │ │
2017-04-26 16:01:13 +00:00
│ ├──────────────────────────────────────────────┤ │
│ │ TOC │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
2017-04-24 12:33:42 +00:00
```
2017-04-28 12:28:25 +00:00
When the index is written, an arbitrary number of padding bytes may be added between the lined out main sections above. When sequentially scanning through the file, any zero bytes after a section's specified length must be skipped.
2017-05-02 10:55:40 +00:00
Most of the sections described below start with a `len` field. It always specifies the number of bytes just before the trailing CRC32 checksum. The checksum is always calculated over those `len` bytes.
2017-04-28 12:28:25 +00:00
2017-04-24 12:33:42 +00:00
### Symbol Table
2024-05-08 15:57:09 +00:00
The symbol table holds a sorted list of deduplicated strings that occur in label pairs of the stored series. They can be referenced from subsequent sections and significantly reduce the total index size.
2017-04-24 12:33:42 +00:00
2017-05-02 10:55:40 +00:00
The section contains a sequence of the string entries, each prefixed with the string's length in raw bytes. All strings are utf-8 encoded.
2018-01-17 04:41:25 +00:00
Strings are referenced by sequential indexing. The strings are sorted in lexicographically ascending order.
2017-04-24 12:33:42 +00:00
```
2017-04-28 12:17:53 +00:00
┌────────────────────┬─────────────────────┐
│ len < 4b > │ #symbols < 4b > │
├────────────────────┴─────────────────────┤
│ ┌──────────────────────┬───────────────┐ │
│ │ len(str_1) < uvarint > │ str_1 < bytes > │ │
│ ├──────────────────────┴───────────────┤ │
│ │ . . . │ │
│ ├──────────────────────┬───────────────┤ │
2018-01-09 15:40:05 +00:00
│ │ len(str_n) < uvarint > │ str_n < bytes > │ │
2017-04-28 12:17:53 +00:00
│ └──────────────────────┴───────────────┘ │
├──────────────────────────────────────────┤
│ CRC32 < 4b > │
└──────────────────────────────────────────┘
2017-04-24 12:33:42 +00:00
```
### Series
2017-04-28 12:17:53 +00:00
The section contains a sequence of series that hold the label set of the series as well as its chunks within the block. The series are sorted lexicographically by their label sets.
2018-01-11 08:36:49 +00:00
Each series section is aligned to 16 bytes. The ID for a series is the `offset/16` . This serves as the series' ID in all subsequent references. Thereby, a sorted list of series IDs implies a lexicographically sorted list of series label sets.
2017-04-24 12:33:42 +00:00
```
2017-04-26 16:01:13 +00:00
┌───────────────────────────────────────┐
│ ┌───────────────────────────────────┐ │
│ │ series_1 │ │
│ ├───────────────────────────────────┤ │
│ │ . . . │ │
│ ├───────────────────────────────────┤ │
│ │ series_n │ │
│ └───────────────────────────────────┘ │
└───────────────────────────────────────┘
2017-04-24 12:33:42 +00:00
```
2017-05-02 10:55:40 +00:00
Every series entry first holds its number of labels, followed by tuples of symbol table references that contain the label name and value. The label pairs are lexicographically sorted.
2017-12-28 07:57:30 +00:00
After the labels, the number of indexed chunks is encoded, followed by a sequence of metadata entries containing the chunks minimum (`mint`) and maximum (`maxt`) timestamp and a reference to its position in the chunk file. The `mint` is the time of the first sample and `maxt` is the time of the last sample in the chunk. Holding the time range data in the index allows dropping chunks irrelevant to queried time ranges without accessing them directly.
2017-04-24 12:33:42 +00:00
2024-02-04 15:31:49 +00:00
Chunk references within single series must be increasing, and chunk references for `series_(N+1)` must be higher than chunk references for `series_N` .
This property guarantees that chunks that belong to the same series are grouped together in the segment files.
Furthermore chunk `mint` must be less or equal than `maxt` , and subsequent chunks within single series must have increasing `mint` and `maxt` and not overlap.
2017-12-28 07:57:30 +00:00
`mint` of the first chunk is stored, it's `maxt` is stored as a delta and the `mint` and `maxt` are encoded as deltas to the previous time for subsequent chunks. Similarly, the reference of the first chunk is stored and the next ref is stored as a delta to the previous one.
2017-09-07 19:05:28 +00:00
2017-04-24 12:33:42 +00:00
```
2019-02-05 16:05:30 +00:00
┌──────────────────────────────────────────────────────────────────────────┐
│ len < uvarint > │
├──────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────────────────────┐ │
2019-02-06 02:00:18 +00:00
│ │ labels count < uvarint64 > │ │
2019-02-05 16:05:30 +00:00
│ ├──────────────────────────────────────────────────────────────────────┤ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ ref(l_i.name) < uvarint32 > │ │ │
2019-02-05 16:34:15 +00:00
│ │ ├────────────────────────────────────────────┤ │ │
2019-02-05 16:05:30 +00:00
│ │ │ ref(l_i.value) < uvarint32 > │ │ │
│ │ └────────────────────────────────────────────┘ │ │
2019-02-05 16:34:15 +00:00
│ │ ... │ │
2019-02-05 16:05:30 +00:00
│ ├──────────────────────────────────────────────────────────────────────┤ │
2019-02-06 02:00:18 +00:00
│ │ chunks count < uvarint64 > │ │
2019-02-05 16:05:30 +00:00
│ ├──────────────────────────────────────────────────────────────────────┤ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ c_0.mint < varint64 > │ │ │
│ │ ├────────────────────────────────────────────┤ │ │
│ │ │ c_0.maxt - c_0.mint < uvarint64 > │ │ │
│ │ ├────────────────────────────────────────────┤ │ │
│ │ │ ref(c_0.data) < uvarint64 > │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ c_i.mint - c_i-1.maxt < uvarint64 > │ │ │
│ │ ├────────────────────────────────────────────┤ │ │
│ │ │ c_i.maxt - c_i.mint < uvarint64 > │ │ │
2019-02-05 16:34:15 +00:00
│ │ ├────────────────────────────────────────────┤ │ │
2019-02-05 16:05:30 +00:00
│ │ │ ref(c_i.data) - ref(c_i-1.data) < varint64 > │ │ │
│ │ └────────────────────────────────────────────┘ │ │
2019-02-05 16:34:15 +00:00
│ │ ... │ │
2019-02-05 16:05:30 +00:00
│ └──────────────────────────────────────────────────────────────────────┘ │
├──────────────────────────────────────────────────────────────────────────┤
│ CRC32 < 4b > │
└──────────────────────────────────────────────────────────────────────────┘
2017-04-24 12:33:42 +00:00
```
### Label Index
2018-01-09 15:40:05 +00:00
A label index section indexes the existing (combined) values for one or more label names.
2022-07-18 11:28:52 +00:00
The `#names` field determines the number of indexed label names, followed by the total number of entries in the `#entries` field. The body holds `#entries / #names` tuples of symbol table references, each tuple being of #names length. The value tuples are sorted in lexicographically increasing order. This is no longer used.
2017-04-24 12:33:42 +00:00
2017-04-25 17:40:52 +00:00
```
2017-04-28 12:17:53 +00:00
┌───────────────┬────────────────┬────────────────┐
│ len < 4b > │ #names < 4b > │ #entries < 4b > │
├───────────────┴────────────────┴────────────────┤
2017-04-26 16:01:13 +00:00
│ ┌─────────────────────────────────────────────┐ │
2017-04-28 12:17:53 +00:00
│ │ ref(value_0) < 4b > │ │
2017-04-26 16:01:13 +00:00
│ ├─────────────────────────────────────────────┤ │
│ │ ... │ │
│ ├─────────────────────────────────────────────┤ │
2017-04-28 12:17:53 +00:00
│ │ ref(value_n) < 4b > │ │
2017-04-26 16:01:13 +00:00
│ └─────────────────────────────────────────────┘ │
2017-04-28 12:17:53 +00:00
│ . . . │
2017-04-26 16:01:13 +00:00
├─────────────────────────────────────────────────┤
2017-04-28 12:17:53 +00:00
│ CRC32 < 4b > │
2017-04-26 16:01:13 +00:00
└─────────────────────────────────────────────────┘
2017-04-25 17:40:52 +00:00
```
2018-01-09 15:40:05 +00:00
For instance, a single label name with 4 different values will be encoded as:
```
┌────┬───┬───┬──────────────┬──────────────┬──────────────┬──────────────┬───────┐
│ 24 │ 1 │ 4 │ ref(value_0) | ref(value_1) | ref(value_2) | ref(value_3) | CRC32 |
└────┴───┴───┴──────────────┴──────────────┴──────────────┴──────────────┴───────┘
```
2019-05-02 20:23:58 +00:00
The sequence of label index sections is finalized by a [label offset table ](#label-offset-table ) containing label offset entries that points to the beginning of each label index section for a given label name.
2017-04-28 12:17:53 +00:00
### Postings
2017-04-24 12:33:42 +00:00
2018-01-09 15:40:05 +00:00
Postings sections store monotonically increasing lists of series references that contain a given label pair associated with the list.
2017-04-26 16:01:13 +00:00
```
2017-04-28 12:17:53 +00:00
┌────────────────────┬────────────────────┐
│ len < 4b > │ #entries < 4b > │
├────────────────────┴────────────────────┤
2017-04-26 16:01:13 +00:00
│ ┌─────────────────────────────────────┐ │
2017-04-28 12:17:53 +00:00
│ │ ref(series_1) < 4b > │ │
2017-04-26 16:01:13 +00:00
│ ├─────────────────────────────────────┤ │
2017-04-28 12:17:53 +00:00
│ │ ... │ │
2017-04-26 16:01:13 +00:00
│ ├─────────────────────────────────────┤ │
2017-04-28 12:17:53 +00:00
│ │ ref(series_n) < 4b > │ │
2017-04-26 16:01:13 +00:00
│ └─────────────────────────────────────┘ │
├─────────────────────────────────────────┤
2017-04-28 12:17:53 +00:00
│ CRC32 < 4b > │
2017-04-26 16:01:13 +00:00
└─────────────────────────────────────────┘
```
2019-05-02 20:23:58 +00:00
The sequence of postings sections is finalized by a [postings offset table ](#postings-offset-table ) containing postings offset entries that points to the beginning of each postings section for a given label pair.
2017-04-28 12:17:53 +00:00
2019-05-02 20:23:58 +00:00
### Label Offset Table
2017-04-28 12:17:53 +00:00
2019-05-02 20:23:58 +00:00
A label offset table stores a sequence of label offset entries.
Every label offset entry holds the label name and the offset to its values in the label index section.
Stream symbols during compaction. (#6468)
Rather than buffer up symbols in RAM, do it one by one
during compaction. Then use the reader's symbol handling
for symbol lookups during the rest of the index write.
There is some slowdown in compaction, due to having to look through a file
rather than a hash lookup. This is noise to the overall cost of compacting
series with thousands of samples though.
benchmark old ns/op new ns/op delta
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=101-4 539917175 675341565 +25.08%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=1001-4 2441815993 2477453524 +1.46%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=2001-4 3978543559 3922909687 -1.40%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=5001-4 8430219716 8586610007 +1.86%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=101-4 1786424591 1909552782 +6.89%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=1001-4 5328998202 6020839950 +12.98%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=2001-4 10085059958 11085278690 +9.92%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=5001-4 25497010155 27018079806 +5.97%
BenchmarkCompactionFromHead/labelnames=1,labelvalues=100000-4 2427391406 2817217987 +16.06%
BenchmarkCompactionFromHead/labelnames=10,labelvalues=10000-4 2592965497 2538805050 -2.09%
BenchmarkCompactionFromHead/labelnames=100,labelvalues=1000-4 2437388343 2668012858 +9.46%
BenchmarkCompactionFromHead/labelnames=1000,labelvalues=100-4 2317095324 2787423966 +20.30%
BenchmarkCompactionFromHead/labelnames=10000,labelvalues=10-4 2600239857 2096973860 -19.35%
benchmark old allocs new allocs delta
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=101-4 500851 470794 -6.00%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=1001-4 821527 791451 -3.66%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=2001-4 1141562 1111508 -2.63%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=5001-4 2141576 2111504 -1.40%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=101-4 871466 841424 -3.45%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=1001-4 1941428 1911415 -1.55%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=2001-4 3071573 3041510 -0.98%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=5001-4 6771648 6741509 -0.45%
BenchmarkCompactionFromHead/labelnames=1,labelvalues=100000-4 731493 824888 +12.77%
BenchmarkCompactionFromHead/labelnames=10,labelvalues=10000-4 793918 887311 +11.76%
BenchmarkCompactionFromHead/labelnames=100,labelvalues=1000-4 811842 905204 +11.50%
BenchmarkCompactionFromHead/labelnames=1000,labelvalues=100-4 832244 925081 +11.16%
BenchmarkCompactionFromHead/labelnames=10000,labelvalues=10-4 921553 1019162 +10.59%
benchmark old bytes new bytes delta
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=101-4 40532648 35698276 -11.93%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=1001-4 60340216 53409568 -11.49%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=2001-4 81087336 72065552 -11.13%
BenchmarkCompaction/type=normal,blocks=4,series=10000,samplesPerSeriesPerBlock=5001-4 142485576 120878544 -15.16%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=101-4 208661368 203831136 -2.31%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=1001-4 347345904 340484696 -1.98%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=2001-4 585185856 576244648 -1.53%
BenchmarkCompaction/type=vertical,blocks=4,series=10000,samplesPerSeriesPerBlock=5001-4 1357641792 1358966528 +0.10%
BenchmarkCompactionFromHead/labelnames=1,labelvalues=100000-4 126486664 119666744 -5.39%
BenchmarkCompactionFromHead/labelnames=10,labelvalues=10000-4 122323192 115117224 -5.89%
BenchmarkCompactionFromHead/labelnames=100,labelvalues=1000-4 126404504 119469864 -5.49%
BenchmarkCompactionFromHead/labelnames=1000,labelvalues=100-4 119047832 112230408 -5.73%
BenchmarkCompactionFromHead/labelnames=10000,labelvalues=10-4 136576016 116634800 -14.60%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-12-17 19:49:54 +00:00
They are used to track label index sections. This is no longer used.
2017-04-28 12:17:53 +00:00
```
2019-02-05 02:28:05 +00:00
┌─────────────────────┬──────────────────────┐
│ len < 4b > │ #entries < 4b > │
├─────────────────────┴──────────────────────┤
│ ┌────────────────────────────────────────┐ │
2019-05-02 20:23:58 +00:00
│ │ n = 1 < 1b > │ │
2019-02-05 02:28:05 +00:00
│ ├──────────────────────┬─────────────────┤ │
2019-05-02 20:23:58 +00:00
│ │ len(name) < uvarint > │ name < bytes > │ │
2019-02-05 02:28:05 +00:00
│ ├──────────────────────┴─────────────────┤ │
2019-05-02 20:23:58 +00:00
│ │ offset < uvarint64 > │ │
│ └────────────────────────────────────────┘ │
│ . . . │
├────────────────────────────────────────────┤
│ CRC32 < 4b > │
└────────────────────────────────────────────┘
```
### Postings Offset Table
Reduce memory used by postings offset table.
Rather than keeping the offset of each postings list, instead
keep the nth offset of the offset of the posting list. As postings
list offsets have always been sorted, we can then get to the closest
entry before the one we want an iterate forwards.
I haven't done much tuning on the 32 number, it was chosen to try
not to read through more than a 4k page of data.
Switch to a bulk interface for fetching postings. Use it to avoid having
to re-read parts of the posting offset table when querying lots of it.
For a index with what BenchmarkHeadPostingForMatchers uses RAM
for r.postings drops from 3.79MB to 80.19kB or about 48x.
Bytes allocated go down by 30%, and suprisingly CPU usage drops by
4-6% for typical queries too.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Block/n="1"-4 35231 36673 +4.09%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 563380 540627 -4.04%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 536782 534186 -0.48%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 533990 541550 +1.42%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113374598 117969608 +4.05%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 146329884 139651442 -4.56%
BenchmarkPostingsForMatchers/Block/i=~""-4 50346510 44961127 -10.70%
BenchmarkPostingsForMatchers/Block/i!=""-4 41261550 35356165 -14.31%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112544418 116904010 +3.87%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 112487086 116864918 +3.89%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 41094758 35457904 -13.72%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 41906372 36151473 -13.73%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 147262414 140424800 -4.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 28615629 27872072 -2.60%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 147117177 140462403 -4.52%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 175096826 167902298 -4.11%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Block/n="1"-4 4 6 +50.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 17 +13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 100010 100012 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 200069 200040 -0.01%
BenchmarkPostingsForMatchers/Block/i=~""-4 200072 200045 -0.01%
BenchmarkPostingsForMatchers/Block/i!=""-4 200070 200041 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 100013 100017 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 100017 100023 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 200073 200046 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 200075 200050 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 200074 200049 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 111165 111150 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 200078 200055 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 311282 311238 -0.01%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Block/n="1"-4 264 296 +12.12%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 520 552 +6.15%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1600461 1600482 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 24900801 17259077 -30.69%
BenchmarkPostingsForMatchers/Block/i=~""-4 24900836 17259151 -30.69%
BenchmarkPostingsForMatchers/Block/i!=""-4 24900760 17259048 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1600557 1600621 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1600717 1600813 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 24900856 17259176 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 24900952 17259304 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 24900993 17259333 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3788311 3142630 -17.04%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 24901137 17259509 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 28693086 20405680 -28.88%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-12-05 18:27:40 +00:00
A postings offset table stores a sequence of postings offset entries, sorted by label name and value.
2019-10-17 11:09:54 +00:00
Every postings offset entry holds the label name/value pair and the offset to its series list in the postings section.
Reduce memory used by postings offset table.
Rather than keeping the offset of each postings list, instead
keep the nth offset of the offset of the posting list. As postings
list offsets have always been sorted, we can then get to the closest
entry before the one we want an iterate forwards.
I haven't done much tuning on the 32 number, it was chosen to try
not to read through more than a 4k page of data.
Switch to a bulk interface for fetching postings. Use it to avoid having
to re-read parts of the posting offset table when querying lots of it.
For a index with what BenchmarkHeadPostingForMatchers uses RAM
for r.postings drops from 3.79MB to 80.19kB or about 48x.
Bytes allocated go down by 30%, and suprisingly CPU usage drops by
4-6% for typical queries too.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Block/n="1"-4 35231 36673 +4.09%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 563380 540627 -4.04%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 536782 534186 -0.48%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 533990 541550 +1.42%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113374598 117969608 +4.05%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 146329884 139651442 -4.56%
BenchmarkPostingsForMatchers/Block/i=~""-4 50346510 44961127 -10.70%
BenchmarkPostingsForMatchers/Block/i!=""-4 41261550 35356165 -14.31%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112544418 116904010 +3.87%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 112487086 116864918 +3.89%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 41094758 35457904 -13.72%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 41906372 36151473 -13.73%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 147262414 140424800 -4.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 28615629 27872072 -2.60%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 147117177 140462403 -4.52%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 175096826 167902298 -4.11%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Block/n="1"-4 4 6 +50.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 17 +13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 100010 100012 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 200069 200040 -0.01%
BenchmarkPostingsForMatchers/Block/i=~""-4 200072 200045 -0.01%
BenchmarkPostingsForMatchers/Block/i!=""-4 200070 200041 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 100013 100017 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 100017 100023 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 200073 200046 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 200075 200050 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 200074 200049 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 111165 111150 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 200078 200055 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 311282 311238 -0.01%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Block/n="1"-4 264 296 +12.12%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 520 552 +6.15%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1600461 1600482 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 24900801 17259077 -30.69%
BenchmarkPostingsForMatchers/Block/i=~""-4 24900836 17259151 -30.69%
BenchmarkPostingsForMatchers/Block/i!=""-4 24900760 17259048 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1600557 1600621 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1600717 1600813 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 24900856 17259176 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 24900952 17259304 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 24900993 17259333 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3788311 3142630 -17.04%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 24901137 17259509 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 28693086 20405680 -28.88%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-12-05 18:27:40 +00:00
They are used to track postings sections. They are partially read into memory when an index file is loaded.
2019-05-02 20:23:58 +00:00
```
┌─────────────────────┬──────────────────────┐
│ len < 4b > │ #entries < 4b > │
├─────────────────────┴──────────────────────┤
│ ┌────────────────────────────────────────┐ │
│ │ n = 2 < 1b > │ │
2019-02-05 02:28:05 +00:00
│ ├──────────────────────┬─────────────────┤ │
2019-05-02 20:23:58 +00:00
│ │ len(name) < uvarint > │ name < bytes > │ │
│ ├──────────────────────┼─────────────────┤ │
│ │ len(value) < uvarint > │ value < bytes > │ │
2019-02-05 02:28:05 +00:00
│ ├──────────────────────┴─────────────────┤ │
│ │ offset < uvarint64 > │ │
│ └────────────────────────────────────────┘ │
│ . . . │
├────────────────────────────────────────────┤
│ CRC32 < 4b > │
└────────────────────────────────────────────┘
2017-04-28 12:17:53 +00:00
```
2017-04-26 16:01:13 +00:00
### TOC
2017-04-28 12:17:53 +00:00
The table of contents serves as an entry point to the entire index and points to various sections in the file.
2017-05-02 10:55:40 +00:00
If a reference is zero, it indicates the respective section does not exist and empty results should be returned upon lookup.
2017-04-26 16:01:13 +00:00
```
2017-04-28 12:17:53 +00:00
┌─────────────────────────────────────────┐
│ ref(symbols) < 8b > │
├─────────────────────────────────────────┤
│ ref(series) < 8b > │
├─────────────────────────────────────────┤
│ ref(label indices start) < 8b > │
├─────────────────────────────────────────┤
2019-05-02 20:23:58 +00:00
│ ref(label offset table) < 8b > │
2017-04-28 12:17:53 +00:00
├─────────────────────────────────────────┤
│ ref(postings start) < 8b > │
├─────────────────────────────────────────┤
2019-05-02 20:23:58 +00:00
│ ref(postings offset table) < 8b > │
2017-04-28 12:17:53 +00:00
├─────────────────────────────────────────┤
│ CRC32 < 4b > │
└─────────────────────────────────────────┘
2017-07-24 20:23:29 +00:00
```