When it does not fit

One bit a key, divided

A levelled store of a million clustered keys, each level's range filter a pair of prefix lengths chosen when the level is written, captures 68% of a perfect filter's saving at two bits a key spread evenly when its keys arrive shuffled, and 94% when they arrive a cluster at a time. The proposal was to divide the memory by what each level's filter saves per bit, and it predicted the memory would leave the small levels, whose keys the arrival order had already sorted out. It goes the other way, as it did for single prefix lengths, and much further: the small levels take twelve to sixteen bits a key, the deepest level one, and the store captures 99% of a perfect filter's saving on both orders while leaving part of the budget unspent. Divided, one bit a key on average does what four bits spread evenly cannot.

The filter rebuilt with every write filled a levelled store of a million keys by insertion and gave each level a range filter made of two prefix lengths, a coarse one and a fine one, chosen from the level’s keys whenever the level is written. A levelled store changes a level’s keys only by rewriting it, so a filter can never go stale, and the essay found that what mattered was not when the lengths were chosen but the order the keys arrived in. The keys sit in sixteen clusters. Filled a cluster at a time, the small levels hold one cluster each, a coarse prefix rules them out of almost every query, and at two bits a key the filters capture 94% of what a perfect filter would save. Filled shuffled, every level holds keys from every cluster, and the filters capture 68%.

That essay’s closing section looked at where the remaining cost sat and proposed moving memory to it. On the store filled a cluster at a time, the small levels’ filters already capture nearly everything at two bits a key, so every bit a key there is spent on a question the coarse prefix has mostly answered. The deepest level, holding fourteen clusters, sits within a few thousandths of a perfect filter. The middle level was where memory could still pay. So it proposed a fixed total of filter memory, divided among the levels in proportion to what each level’s filter would save per bit and re-divided at every write. It predicted that on the store filled a cluster at a time almost all the memory would move to the middle and deepest levels, the store’s cost falling by a few hundredths of a transfer a query, and that on the shuffled store the even split was already close to right.

Dividing a budget by what it buys

The store, its keys and its queries are the earlier essays’. 2^20 keys in sixteen clusters are inserted into a levelled store with a buffer of 4,096 keys and levels growing fourfold; at every write a level’s filter is rebuilt with the best pair of prefix lengths for its keys. A query asks a range expected to hold 0.1, 1, 10 or 100 keys, half placed anywhere and half centred on a stored key, and costs a transfer for every level the filter fails to skip and a transfer for every block of keys a level holds in range. A perfect filter skips every level holding nothing of the range and nothing else.

For each level, and for every number of bits a key on a grid from nought to sixteen, the best pair is chosen and the level’s cost is read. The division is the assignment of a grid value to every level, within a budget of memory, that makes the whole store cheapest; with three to five levels and ten grid values the search is exhaustive. The division is found on one seed of queries and charged on another, so it is not fitted to the queries it is scored on. The even split gives every level the average. The search is the exact optimum the proposal’s rule of thumb, memory in proportion to what it saves per bit, was a way of approximating.

Through the fill

At 2 bits a key on average, dividing the memory by what it saves captures 78% or more of a perfect filter's saving at every point of the shuffled fill, where an even split captures 67% to 72%; filled a cluster at a time, 97% or more against 91% to 99%Through the fill of a levelled store of 2^20 keys in sixteen clusters, at six points, the share of a perfect filter's saving over no filter captured by range filters with 2 bits a key on average, split evenly across the levels or divided by the division cheapest on a choosing seed of queries, charged on a fresh seed. shuffled, even: 13% 67.4%, 25% 71.6%, 38% 69.7%, 50% 72.4%, 75% 70.6%, 100% 67.5%. shuffled, divided: 13% 77.7%, 25% 94.7%, 38% 95.2%, 50% 93.3%, 75% 95.8%, 100% 99.0%. a cluster at a time, even: 13% 90.9%, 25% 98.8%, 38% 93.6%, 50% 98.3%, 75% 98.5%, 100% 94.2%. a cluster at a time, divided: 13% 97.4%, 25% 99.8%, 38% 99.9%, 50% 99.6%, 75% 99.7%, 100% 99.6%.50%60%70%80%90%100%the store's fill, share of its 1,048,576 keysshare of a perfect filter's saving captured13%25%38%50%75%100%a cluster at a time, dividedshuffled, divideda cluster at a time, evenshuffled, even2 bits a key on averagedashed: the same bits on every level
Fig. 1 The share of a perfect filter’s saving captured at two bits a key on average, at six points of the fill. Shuffled, split evenly: 67% to 72%; divided: 78% at an eighth full, then 93% to 99%. A cluster at a time, split evenly: 91% to 99%; divided: 97% to 99.9%.

Divided by what each level saves, two bits a key capture 99% of a perfect filter’s saving on the full store whichever order the keys arrived in, against 68% and 94% split evenly. On the shuffled store the division recovers almost the whole of what the earlier essay found missing; on the store filled a cluster at a time it recovers the last six points. Through the fill the picture holds from a quarter full on. Only at an eighth full, with three levels and the deepest still small, does the shuffled store’s division stop at 78%.

The prediction had the size of the gain backwards as well as the direction. It expected a few hundredths of a transfer a query on the store filled a cluster at a time and little on the shuffled one. The gain is 0.13 transfers a query filled a cluster at a time and 0.59 shuffled, a tenth of the store’s whole cost.

The full store, level by level

On the full store the division gives back what the small levels lose: shuffled, the 4,096-key level costs 0.81 transfers a query split evenly and 0.41 divided, the 61,440-key level 1.11 and 0.91, and the deepest 4.64 either way, against a perfect filter's 4.64Transfers a query on each level of the full store, at 2 bits a key on average, for the even split (upper bar) and the division (lower bar), with a perfect filter's cost marked. shuffled, 4,096 keys: even 0.809, divided 0.411 at 16 bits a key, perfect 0.404, none 1.202. shuffled, 61,440 keys: even 1.108, divided 0.911 at 16 bits a key, perfect 0.905, none 1.527. shuffled, 983,040 keys: even 4.641, divided 4.641 at 1 bits a key, perfect 4.635, none 5.106. a cluster at a time, 4,096 keys: even 0.207, divided 0.071 at 12 bits a key, perfect 0.069, none 1.040. a cluster at a time, 61,440 keys: even 0.357, divided 0.362 at 12 bits a key, perfect 0.357, none 1.309. a cluster at a time, 983,040 keys: even 4.537, divided 4.537 at 1 bits a key, perfect 4.535, none 5.046. Store totals: shuffled 6.558 and 5.964, a cluster at a time 5.102 and 4.971.012345transfers a query on the levelshuffled, 4,096 keysdivided: 16 bits a keyshuffled, 61,440 keysdivided: 16 bits a keyshuffled, 983,040 keysdivided: 1 bit a keya cluster at a time, 4,096 keysdivided: 12 bits a keya cluster at a time, 61,440 keysdivided: 12 bits a keya cluster at a time, 983,040 keysdivided: 1 bit a keyupper: even · lower: divided · line: a perfect filter2 bits a key on average
Fig. 2 Transfers a query on each level of the full store at two bits a key on average, split evenly and divided, against a perfect filter. Shuffled: the 4,096-key level 0.809 even and 0.411 divided, perfect 0.404; the 61,440-key level 1.108 and 0.911, perfect 0.905; the deepest, 983,040 keys, 4.641 either way, perfect 4.635. A cluster at a time: 0.207 and 0.071; 0.357 and 0.362; 4.537 and 4.537.

Every transfer the division saves is on the two small levels; the deepest level costs the same, within six thousandths of a perfect filter, under both splits. On the shuffled store the smallest level’s cost halves, from 0.809 transfers a query to 0.411, and the middle level’s falls from 1.108 to 0.911. Each lands within a hundredth of what a perfect filter would cost it.

The small levels cost as much as they do because they are small. A range the store holds keys in usually reaches the deepest level, which holds 94% of the keys, and that reach is a transfer nobody can avoid. The small levels hold a few thousand keys each, scattered over all sixteen clusters when the store is shuffled, and a range asks each of them whether it holds anything; at two bits a key their filters answer wrongly often enough to cost six tenths of a transfer a query more than a perfect filter between them. On the store filled a cluster at a time the small levels hold one cluster each and are wrongly asked much less, which is why the even split did well there and why the division has less to give.

Where the bits go

The division gives the small levels the most bits a key and the deepest the fewest, the reverse of an even split: on the full store at 2 bits on average, shuffled 16, 16, 1; a cluster at a time 12, 12, 1 bits a key from the smallest level to the deepestThe bits a key given to every level by the division at 2 bits a key on average, against the level's size, at every point of both fills (one point a level and a point of the fill). shuffled: 13% full, 8,192 keys 6, 40,960 keys 3, 81,920 keys 1; 25% full, 16,384 keys 16, 245,760 keys 1; 38% full, 4,096 keys 16, 61,440 keys 6, 327,680 keys 1; 50% full, 12,288 keys 12, 20,480 keys 12, 163,840 keys 2, 327,680 keys 1; 75% full, 8,192 keys 12, 40,960 keys 12, 81,920 keys 8, 655,360 keys 0.5; 100% full, 4,096 keys 16, 61,440 keys 16, 983,040 keys 1. a cluster at a time: 13% full, 8,192 keys 12, 40,960 keys 2, 81,920 keys 1; 25% full, 16,384 keys 16, 245,760 keys 1; 38% full, 4,096 keys 16, 61,440 keys 1, 327,680 keys 1; 50% full, 12,288 keys 12, 20,480 keys 12, 163,840 keys 2, 327,680 keys 1; 75% full, 8,192 keys 12, 40,960 keys 12, 81,920 keys 4, 655,360 keys 1; 100% full, 4,096 keys 12, 61,440 keys 12, 983,040 keys 1.02481216keys on the level (log scale)bits a key the division gives it4,09616,38465,536262,1441,048,576the even splitshuffleda cluster at a timeevery level at every point of the fill2 bits a key on average
Fig. 3 The bits a key the division gives each level, against the level’s size, at every point of both fills at two bits a key on average. Levels of 4,096 to 61,440 keys: 6 to 16 bits a key, mostly 12 or 16. Levels of 245,760 keys or more: one bit a key or half a bit. On the full store, shuffled: 16, 16 and 1; a cluster at a time: 12, 12 and 1.

The division gives the small levels twelve to sixteen bits a key and the deepest one bit, at every point of both fills. It is the reverse of the even split and the reverse of what the proposal expected. The proposal reasoned from where the filters were already good; the division reasons from what a bit a key buys on each level, and on a small level a bit a key is cheap in total memory and buys a great deal.

The small levels’ share of a range filter found the same direction for single prefix lengths on a static four-level store, 12, 12, 8 and 3 bits a key instead of 5 each, recovering half the gap to a perfect filter; the filter each run carries found it for point lookups. What is new here is how far it goes with a pair of lengths. One bit a key on the deepest level costs nothing measurable, because its coarse prefix rules out the gaps between clusters and its fine prefix needs little memory to separate keys that a level so dense holds in nearly every range anyway. And the arrival order, which decided so much at an even split, decides almost nothing once the memory is divided.

What a bit buys on each level

What a bit a key buys depends on the level: on the full shuffled store the deepest level, 983,040 keys, has 1.1% of its avoidable cost left at one bit, while the 4,096-key level still pays 25% of its avoidable cost at four bits and needs twelve to sixteenOn the full store filled shuffled, each level's cost above a perfect filter's, as a share of the cost no filter leaves above it, against the bits a key its filter is given. 4,096 keys: 0 100.0%, 0.5 88.3%, 1 69.3%, 2 50.8%, 3 33.3%, 4 24.7%, 6 12.8%, 8 6.8%, 12 3.0%, 16 0.9%. 61,440 keys: 0 100.0%, 0.5 74.9%, 1 54.1%, 2 32.7%, 3 22.6%, 4 17.6%, 6 9.7%, 8 5.5%, 12 2.5%, 16 1.0%. 983,040 keys: 0 100.0%, 0.5 2.2%, 1 1.1%, 2 1.1%, 3 1.1%, 4 1.1%, 6 1.1%, 8 1.1%, 12 1.1%, 16 0.2%.0%25%50%75%100%02481216bits a key on this level's filtershare of the level's avoidable cost left61,440 keys4,096 keys983,040 keys0% = a perfect filter, 100% = no filterthe full store, shuffled
Fig. 4 On the full shuffled store, each level’s cost above a perfect filter’s, as a share of what no filter leaves above it, against its filter’s bits a key. The deepest level: 100% with no filter, 2.3% at half a bit, 1.3% at one. The 61,440-key level: 54% at one bit, 18% at four, 1.0% at sixteen. The 4,096-key level: 69% at one bit, 25% at four, 0.9% at sixteen.

The deepest level has 2.3% of its avoidable cost left at half a bit a key and 1.3% at one, and the two small levels need sixteen bits a key to get that close. That is the whole of the division’s reasoning on one plate. Half a bit a key on 983,040 keys is half a million bits; sixteen bits a key on the 65,536 keys of the two small levels together is a million. The even split’s two bits a key put two million bits on the deepest level, where everything past one bit a key buys almost nothing, and an eighth of a million on the small levels, where those few bits buy only half to two thirds of the saving that was there.

The curves’ shapes are the reason a budget divided this way stops spending. Past sixteen bits a key the small levels’ curves have nowhere left to fall, and the deepest level’s is flat from one bit on. At two bits a key on average the division spends 1.94 bits on the shuffled store and 1.69 on the store filled a cluster at a time; more memory buys nothing the grid can find.

Why the deepest level needs so little

The deepest level holds 94% of the keys and every one of the sixteen clusters, so it is the level a range is least able to skip. Half the queries are centred on a stored key, and those meet the deepest level almost always, which a perfect filter charges as well. The other half are placed anywhere in the key space, and fifteen times in sixteen they fall between clusters. Two lengths that do the work of eleven built the pair for exactly that mixture: a coarse prefix that rules out the empty stretches between clusters with few bits, and a fine one for the ranges that land in a cluster. On a level this dense the fine prefix has little to do, because a range that lands inside a cluster usually does hold one of the level’s keys, and the coarse prefix needs only a few hundred prefixes to cover the clusters. Both fit in half a bit a key. At one bit a key the deepest level on the shuffled store chooses twelve and twenty bits, the same pair it chooses at eight. A twelve-bit prefix divides the key space into 4,096 parts, and the sixteen clusters, a sixteenth of the space, occupy about 256 of them; a filter that holds those 256 rules out almost every range between clusters with a few thousand bits. The small levels, given sixteen bits a key, move their fine length out to 23 and 25 bits, spending the memory on resolution inside the clusters.

The small levels are the opposite case. A few thousand keys scattered over every cluster leave most short ranges inside a cluster empty, so the fine prefix has real work and needs memory to do it without false positives. The runs a range query can skip found that by ranges of a hundred keys only the smallest level is ever empty; the small levels are where a range filter’s decisions are made, and the deepest level is where it confirms what was already likely.

How much memory the store needs

Divided, one bit a key on average does what four bits a key spread evenly cannot: on the full shuffled store it captures 97.2% of a perfect filter's saving, against 83.5% for an even fourOn the full store, the share of a perfect filter's saving captured at 0.5, 1, 2, 4 bits a key on average, split evenly or divided by what each level saves. shuffled, even: 0.5 37.6%, 1 52.7%, 2 67.5%, 4 83.5%. shuffled, divided: 0.5 71.5%, 1 97.2%, 2 99.0%, 4 99.0%. a cluster at a time, even: 0.5 69.8%, 1 82.4%, 2 94.2%, 4 98.8%. a cluster at a time, divided: 0.5 78.9%, 1 99.8%, 2 99.6%, 4 99.6%.50%75%100%bits a key on averageshare of a perfect filter's saving captured0.5124a cluster at a time, dividedshuffled, divideda cluster at a time, evenshuffled, eventhe full storedashed: the same bits on every level
Fig. 5 The share of a perfect filter’s saving captured on the full store at 0.5, 1, 2 and 4 bits a key on average. Shuffled, even: 38%, 53%, 68%, 84%; divided: 72%, 97%, 99%, 99%. A cluster at a time, even: 70%, 82%, 94%, 99%; divided: 79%, 99.8%, 99.6%, 99.6%.

Divided, one bit a key on average captures 97% of a perfect filter’s saving on the shuffled store; spread evenly, four bits a key capture 84%. The memory a range filter needs on this store is about one bit a key, if it is put where it buys something. Half a bit is too little for any division: the small levels can be given sixteen bits a key only by starving the deepest level to nothing, and a deepest level with no filter costs half a transfer a query.

The divided curves are flat from one bit on because the grid stops at sixteen bits a key and there is nothing left to buy. The last per cent between the division and a perfect filter is the small levels’ remaining false positives at sixteen bits a key and the deepest level’s at one, and closing it would take more bits on levels whose curves are already flat.

Where the memory goes

Spread evenly, the deepest level takes 94% of the filter memory because it holds that share of the keys; divided, it takes 47% on the shuffled store, the small levels take 50%, and 3% of the budget is left unspentOn the full store at 2 bits a key on average, each level's share of the filter memory under the even split and under the division, smallest level first (4,096, 61,440, 983,040 keys), with any budget the division leaves unspent. shuffled, even: 0.4%, 5.9%, 93.8%. shuffled, divided: 3.1%, 46.9%, 46.9%, unspent 3.1%. a cluster at a time, even: 0.4%, 5.9%, 93.8%. a cluster at a time, divided: 2.3%, 35.2%, 46.9%, unspent 15.6%.4,096 keys61,440 keys983,040 keys0%25%50%75%100%share of the filter memoryshuffled, evenshuffled, divided3% unspenta cluster at a time, evena cluster at a time, divided16% unspentthe full store2 bits a key on average
Fig. 6 Each level’s share of the filter memory on the full store at two bits a key on average. Split evenly, the shares follow the keys: 0.4%, 5.9% and 93.8%. Divided, shuffled: 3.1%, 46.9% and 46.9%, with 3.1% unspent. Divided, a cluster at a time: 2.3%, 35.2% and 46.9%, with 15.6% unspent.

Divided, the two small levels hold 6% of the keys and get half the memory on the shuffled store; the deepest level, 94% of the keys, gets the other half at one bit a key. On the store filled a cluster at a time the division leaves a sixth of the budget unspent, because the small levels’ single clusters are ruled out cheaply and twelve bits a key already finishes them.

The re-division at every write the proposal asked for comes free with the store. A levelled store rewrites a level whole, and rebuilds its filter, every time the level changes, so it can size the filter to the level’s current share at that moment. Those rewrites are the write cost the writes nobody counted measured, two elements written for every key stored, and they are paid whether or not the filter is resized; a division recomputed at each write adds the arithmetic of choosing and nothing else. The earlier essay priced choosing a pair at every write at 28 times the hashing of building one filter; a division adds a choice of bits a key to that choice of lengths, and the grid here multiplies the candidates by ten. The division plate through the fill is exactly that: at every point the levels’ sizes differ, and the division follows them.

What the counts depend on

The division is fitted to the workload. It is found by trying every assignment against one seed of the actual queries, and charged on another seed of the same mixture. A store choosing its division before its queries arrive would have to predict what a bit a key buys on each level; the plate of curves shows the shape, and nothing here shows how well a prediction would track it.

A grid of bits a key. The levels are offered nought, half a bit and 1, 2, 3, 4, 6, 8, 12 and 16 bits a key. A finer grid would spend the leftover budget and close part of the last per cent; a coarser one would not change the direction.

Range queries only. The workload asks ranges, and the filters are prefix filters. A store answering point lookups as well would want its deepest level’s filter to separate keys, which half a bit a key cannot do; the read a filter has no key for measured how differently the two kinds of query use the same memory. A division for a mixed workload would weigh both, and was not measured.

One store, two orders. The keys are the earlier pages’ sixteen clusters. A store whose keys are spread uniformly would have small levels that a coarse prefix cannot rule out, and the division would have more to buy there.

Still open: a division chosen before the queries arrive

The division here was found by trying every assignment against the store’s own queries, which a store cannot do when it writes a level. It knows its levels’ sizes, and it knows what its filters do on its keys only by asking queries it has not yet been asked. The small levels’ share of a range filter and the filter each run carries both point at a division set by the levels’ sizes alone: a level’s false-positive cost is about the same for every level per query, so the bits a key should grow by a fixed amount for every factor of four by which a level is smaller.

The measurement that follows divides the memory by that rule, from the sizes alone, with the extra bits a key per factor of four as its one parameter, and charges it on both orders through the fill against the division found here. The prediction is that on the shuffled store the rule comes within a point of the fitted division’s 99%, since the levels’ curves there differ mainly in their sizes, and that on the store filled a cluster at a time it gives the small levels bits they do not need, landing at the even split’s 94% or a little above. It could fail on the deepest level. The rule gives it the fewest bits a key, but if it gives it less than half a bit, the deepest level’s curve is steep there, and a rule tuned to the small levels could lose more on the deepest than it gains on them. The question is whether a store can size its filters from its levels’ sizes, or whether what a bit buys depends on where the keys sit, which only the queries can say.

Named alongside this one

Essays reaching for the same objects. Nobody chose these; they are what the concept index makes visible.

The objects this essay names

Each one links to every other essay that touches it.

Bloom filterDesign parameterLsm treePer levelRange queryRead amplificationSpace accountingWorkload