Skip to content

Commit b0a0f0e

Browse files
committed
manifest: make internal range key bound of TableMetadata a pointer
Since range keys are rare, we make our range key bounds a pointer to save on 32 bytes. Informs: #2047
1 parent 3618106 commit b0a0f0e

File tree

11 files changed

+52
-38
lines changed

11 files changed

+52
-38
lines changed

db.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3043,7 +3043,7 @@ func (d *DB) checkVirtualBounds(m *tableMetadata) {
30433043
// Check that the lower bound is tight.
30443044
if s, err := rangeKeyIter.First(); err != nil {
30453045
panic(err)
3046-
} else if d.cmp(s.SmallestKey().UserKey, m.RangeKeyBounds.SmallestUserKey()) != 0 {
3046+
} else if m.HasRangeKeys && d.cmp(s.SmallestKey().UserKey, m.RangeKeyBounds.SmallestUserKey()) != 0 {
30473047
panic(errors.Newf("pebble: virtual sstable %s lower range key bound is not tight", m.FileNum))
30483048
}
30493049

file_cache_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ func TestVirtualReadsWiring(t *testing.T) {
372372
}
373373
v2.PointKeyBounds.SetInternalKeyBounds(base.MakeInternalKey([]byte{'d'}, seqNumCEDel, InternalKeyKindRangeDelete),
374374
base.MakeInternalKey([]byte{'z'}, seqNumZ, InternalKeyKindSet))
375+
v2.RangeKeyBounds = &manifest.InternalKeyBounds{}
375376
v2.RangeKeyBounds.SetInternalKeyBounds(
376377
base.MakeInternalKey([]byte{'f'}, seqNumRangeSet, InternalKeyKindRangeKeySet),
377378
base.MakeInternalKey([]byte{'k'}, seqNumRangeUnset, InternalKeyKindRangeKeyUnset))

ingest_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ func TestIngestLoad(t *testing.T) {
155155
for _, m := range lr.local {
156156
fmt.Fprintf(&buf, "%d: %s-%s\n", m.FileNum, m.Smallest(), m.Largest())
157157
fmt.Fprintf(&buf, " points: %s-%s\n", m.PointKeyBounds.Smallest(), m.PointKeyBounds.Largest())
158-
fmt.Fprintf(&buf, " ranges: %s-%s\n", m.RangeKeyBounds.Smallest(), m.RangeKeyBounds.Largest())
158+
if m.HasRangeKeys {
159+
fmt.Fprintf(&buf, " ranges: %s-%s\n", m.RangeKeyBounds.Smallest(), m.RangeKeyBounds.Largest())
160+
}
159161
}
160162
return buf.String()
161163

@@ -2660,7 +2662,9 @@ func TestIngest_UpdateSequenceNumber(t *testing.T) {
26602662
fmt.Fprintf(&buf, "file %d:\n", i)
26612663
fmt.Fprintf(&buf, " combined: %s-%s\n", m.Smallest(), m.Largest())
26622664
fmt.Fprintf(&buf, " points: %s-%s\n", m.PointKeyBounds.Smallest(), m.PointKeyBounds.Largest())
2663-
fmt.Fprintf(&buf, " ranges: %s-%s\n", m.RangeKeyBounds.Smallest(), m.RangeKeyBounds.Largest())
2665+
if m.HasRangeKeys {
2666+
fmt.Fprintf(&buf, " ranges: %s-%s\n", m.RangeKeyBounds.Smallest(), m.RangeKeyBounds.Largest())
2667+
}
26642668
}
26652669

26662670
return buf.String()

internal/keyspan/keyspanimpl/level_iter_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ func TestLevelIterEquivalence(t *testing.T) {
296296
HasRangeKeys: true,
297297
}
298298
meta.InitPhysicalBacking()
299+
meta.RangeKeyBounds = &manifest.InternalKeyBounds{}
299300
meta.RangeKeyBounds.SetInternalKeyBounds(
300301
base.MakeInternalKey(file[0].Start, file[0].SmallestKey().SeqNum(), file[0].SmallestKey().Kind()),
301302
base.MakeExclusiveSentinelKey(file[len(file)-1].LargestKey().Kind(), file[len(file)-1].End))

internal/manifest/version.go

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,16 @@ func (ikr *InternalKeyBounds) Largest() InternalKey {
8181
}
8282

8383
func (ikr *InternalKeyBounds) SetSmallest(ik InternalKey) {
84-
largest := ikr.Largest()
85-
ikr.userKeyData = string(ik.UserKey) + string(largest.UserKey)
84+
ikr.userKeyData = string(ik.UserKey) + string(ikr.LargestUserKey())
8685
ikr.smallestTrailer = ik.Trailer
8786
ikr.userKeySeparatorIdx = len(ik.UserKey)
8887
}
8988

9089
func (ikr *InternalKeyBounds) SetLargest(ik InternalKey) {
91-
smallest := ikr.Smallest()
92-
ikr.userKeyData = string(smallest.UserKey) + string(ik.UserKey)
90+
smallestUserKey := ikr.SmallestUserKey()
91+
ikr.userKeyData = string(smallestUserKey) + string(ik.UserKey)
9392
ikr.largestTrailer = ik.Trailer
94-
ikr.userKeySeparatorIdx = len(smallest.UserKey)
93+
ikr.userKeySeparatorIdx = len(smallestUserKey)
9594
}
9695

9796
// TableInfo contains the common information for table related events.
@@ -237,8 +236,8 @@ func (s CompactionState) String() string {
237236
//
238237
// When using these fields in the context of a Virtual Table, These fields
239238
// have additional invariants imposed on them, and/or slightly varying meanings:
240-
// - Smallest and Largest (and their counterparts
241-
// {Smallest, Largest}{Point,Range}Key) remain tight bounds that represent a
239+
// - boundTypeSmallest and boundTypeLargest (and their counterparts
240+
// {Point,Range}KeyBounds.{Smallest(), Largest()}) remain tight bounds that represent a
242241
// key at that exact bound. We make the effort to determine the next smallest
243242
// or largest key in an sstable after virtualizing it, to maintain this
244243
// tightness. If the largest is a sentinel key (IsExclusiveSentinel()), it
@@ -323,7 +322,7 @@ type TableMetadata struct {
323322
// internal range keys stored in the table.
324323
// NB: these field should be set using ExtendRangeKeyBounds. They are left
325324
// exported for reads as an optimization.
326-
RangeKeyBounds InternalKeyBounds
325+
RangeKeyBounds *InternalKeyBounds
327326
// BlobReferences is a list of blob files containing values that are
328327
// referenced by this sstable.
329328
BlobReferences BlobReferences
@@ -472,6 +471,9 @@ func (m *TableMetadata) UserKeyBoundsByType(keyType KeyType) base.UserKeyBounds
472471
case KeyTypePoint:
473472
return base.UserKeyBoundsFromInternal(m.PointKeyBounds.Smallest(), m.PointKeyBounds.Largest())
474473
case KeyTypeRange:
474+
if !m.HasRangeKeys {
475+
return base.UserKeyBounds{}
476+
}
475477
return base.UserKeyBoundsFromInternal(m.RangeKeyBounds.Smallest(), m.RangeKeyBounds.Largest())
476478
default:
477479
return base.UserKeyBoundsFromInternal(m.Smallest(), m.Largest())
@@ -723,6 +725,7 @@ func (m *TableMetadata) ExtendRangeKeyBounds(
723725
) *TableMetadata {
724726
// Update the range key bounds.
725727
if !m.HasRangeKeys {
728+
m.RangeKeyBounds = &InternalKeyBounds{}
726729
m.RangeKeyBounds.SetInternalKeyBounds(smallest, largest)
727730
m.HasRangeKeys = true
728731
} else {
@@ -795,11 +798,13 @@ func (m *TableMetadata) ContainsKeyType(kt KeyType) bool {
795798
func (m *TableMetadata) SmallestBound(kt KeyType) (InternalKey, bool) {
796799
switch kt {
797800
case KeyTypePointAndRange:
798-
ik := m.Smallest()
799-
return ik, true
801+
return m.Smallest(), true
800802
case KeyTypePoint:
801803
return m.PointKeyBounds.Smallest(), m.HasPointKeys
802804
case KeyTypeRange:
805+
if !m.HasRangeKeys {
806+
return InternalKey{}, m.HasRangeKeys
807+
}
803808
return m.RangeKeyBounds.Smallest(), m.HasRangeKeys
804809
default:
805810
panic("unrecognized key type")
@@ -817,6 +822,9 @@ func (m *TableMetadata) LargestBound(kt KeyType) (InternalKey, bool) {
817822
case KeyTypePoint:
818823
return m.PointKeyBounds.Largest(), m.HasPointKeys
819824
case KeyTypeRange:
825+
if !m.HasRangeKeys {
826+
return InternalKey{}, m.HasRangeKeys
827+
}
820828
return m.RangeKeyBounds.Largest(), m.HasRangeKeys
821829
default:
822830
panic("unrecognized key type")
@@ -961,6 +969,7 @@ func ParseTableMetadataDebug(s string) (_ *TableMetadata, err error) {
961969
p.Expect("]")
962970

963971
case "ranges":
972+
m.RangeKeyBounds = &InternalKeyBounds{}
964973
p.Expect("[")
965974
smallest := p.InternalKey()
966975
p.Expect("-")
@@ -999,13 +1008,12 @@ func ParseTableMetadataDebug(s string) (_ *TableMetadata, err error) {
9991008
cmp := base.DefaultComparer.Compare
10001009
if base.InternalCompare(cmp, smallest, m.PointKeyBounds.Smallest()) == 0 {
10011010
m.boundTypeSmallest = boundTypePointKey
1002-
1003-
} else if base.InternalCompare(cmp, smallest, m.RangeKeyBounds.Smallest()) == 0 {
1011+
} else if m.HasRangeKeys && base.InternalCompare(cmp, smallest, m.RangeKeyBounds.Smallest()) == 0 {
10041012
m.boundTypeSmallest = boundTypeRangeKey
10051013
}
10061014
if base.InternalCompare(cmp, largest, m.PointKeyBounds.Largest()) == 0 {
10071015
m.boundTypeLargest = boundTypePointKey
1008-
} else if base.InternalCompare(cmp, largest, m.RangeKeyBounds.Largest()) == 0 {
1016+
} else if m.HasRangeKeys && base.InternalCompare(cmp, largest, m.RangeKeyBounds.Largest()) == 0 {
10091017
m.boundTypeLargest = boundTypeRangeKey
10101018
}
10111019

@@ -1192,6 +1200,9 @@ func (m *TableMetadata) Smallest() InternalKey {
11921200
case boundTypePointKey:
11931201
return m.PointKeyBounds.Smallest()
11941202
case boundTypeRangeKey:
1203+
if !m.HasRangeKeys {
1204+
return InternalKey{}
1205+
}
11951206
return m.RangeKeyBounds.Smallest()
11961207
default:
11971208
return InternalKey{}
@@ -1205,6 +1216,9 @@ func (m *TableMetadata) Largest() InternalKey {
12051216
case boundTypePointKey:
12061217
return m.PointKeyBounds.Largest()
12071218
case boundTypeRangeKey:
1219+
if !m.HasRangeKeys {
1220+
return InternalKey{}
1221+
}
12081222
return m.RangeKeyBounds.Largest()
12091223
default:
12101224
return InternalKey{}

internal/manifest/version_edit.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ func (v *VersionEdit) Decode(r io.Reader) error {
478478
m.HasPointKeys = true
479479
}
480480
// Set range key bounds.
481+
m.RangeKeyBounds = &InternalKeyBounds{}
481482
m.RangeKeyBounds.SetInternalKeyBounds(base.DecodeInternalKey(smallestRangeKey),
482483
base.DecodeInternalKey(largestRangeKey))
483484
m.HasRangeKeys = true
@@ -775,9 +776,11 @@ func (v *VersionEdit) Encode(w io.Writer) error {
775776
e.writeKey(x.Meta.PointKeyBounds.Smallest())
776777
e.writeKey(x.Meta.PointKeyBounds.Largest())
777778
}
778-
// Write range key bounds.
779-
e.writeKey(x.Meta.RangeKeyBounds.Smallest())
780-
e.writeKey(x.Meta.RangeKeyBounds.Largest())
779+
// Write range key bounds (if present).
780+
if x.Meta.HasRangeKeys {
781+
e.writeKey(x.Meta.RangeKeyBounds.Smallest())
782+
e.writeKey(x.Meta.RangeKeyBounds.Largest())
783+
}
781784
}
782785
e.writeUvarint(uint64(x.Meta.SmallestSeqNum))
783786
e.writeUvarint(uint64(x.Meta.LargestSeqNum))

internal/manifest/version_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ func TestTableMetadataSize(t *testing.T) {
846846
}
847847
structSize := unsafe.Sizeof(TableMetadata{})
848848

849-
const tableMetadataSize = 400
849+
const tableMetadataSize = 368
850850
if structSize != tableMetadataSize {
851851
t.Errorf("TableMetadata struct size (%d bytes) is not expected size (%d bytes)",
852852
structSize, tableMetadataSize)

scan_internal.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,15 @@ func (s *SharedSSTMeta) cloneFromFileMeta(f *tableMetadata) {
9393
*s = SharedSSTMeta{
9494
Smallest: f.Smallest().Clone(),
9595
Largest: f.Largest().Clone(),
96-
SmallestRangeKey: f.RangeKeyBounds.Smallest().Clone(),
97-
LargestRangeKey: f.RangeKeyBounds.Largest().Clone(),
9896
SmallestPointKey: f.PointKeyBounds.Smallest().Clone(),
9997
LargestPointKey: f.PointKeyBounds.Largest().Clone(),
10098
Size: f.Size,
10199
fileNum: f.FileNum,
102100
}
101+
if f.HasRangeKeys {
102+
s.SmallestRangeKey = f.RangeKeyBounds.Smallest().Clone()
103+
s.LargestRangeKey = f.RangeKeyBounds.Largest().Clone()
104+
}
103105
}
104106

105107
type sharedByLevel []SharedSSTMeta

table_stats.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,9 +1028,11 @@ func newCombinedDeletionKeyspanIter(
10281028
if iter != nil {
10291029
// Assert expected bounds in tests.
10301030
if invariants.Sometimes(50) {
1031-
iter = keyspan.AssertBounds(
1032-
iter, m.RangeKeyBounds.Smallest(), m.RangeKeyBounds.LargestUserKey(), comparer.Compare,
1033-
)
1031+
if m.HasRangeKeys {
1032+
iter = keyspan.AssertBounds(
1033+
iter, m.RangeKeyBounds.Smallest(), m.RangeKeyBounds.LargestUserKey(), comparer.Compare,
1034+
)
1035+
}
10341036
}
10351037
// Wrap the range key iterator in a filter that elides keys other than range
10361038
// key deletions.

testdata/ingest_load

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,76 +17,66 @@ a.SET.0:
1717
----
1818
1: a#0,SET-a#0,SET
1919
points: a#0,SET-a#0,SET
20-
ranges: #0,DEL-#0,DEL
2120

2221
load
2322
a.SET.0:
2423
b.SET.0:
2524
----
2625
1: a#0,SET-b#0,SET
2726
points: a#0,SET-b#0,SET
28-
ranges: #0,DEL-#0,DEL
2927

3028
load
3129
a.DEL.0:
3230
----
3331
1: a#0,DEL-a#0,DEL
3432
points: a#0,DEL-a#0,DEL
35-
ranges: #0,DEL-#0,DEL
3633

3734
load
3835
a.DEL.0:
3936
b.DEL.0:
4037
----
4138
1: a#0,DEL-b#0,DEL
4239
points: a#0,DEL-b#0,DEL
43-
ranges: #0,DEL-#0,DEL
4440

4541
load
4642
a.MERGE.0:
4743
----
4844
1: a#0,MERGE-a#0,MERGE
4945
points: a#0,MERGE-a#0,MERGE
50-
ranges: #0,DEL-#0,DEL
5146

5247
load
5348
a.MERGE.0:
5449
b.MERGE.0:
5550
----
5651
1: a#0,MERGE-b#0,MERGE
5752
points: a#0,MERGE-b#0,MERGE
58-
ranges: #0,DEL-#0,DEL
5953

6054
load
6155
Span: a-b:{(#0,RANGEDEL)}
6256
----
6357
1: a#0,RANGEDEL-b#inf,RANGEDEL
6458
points: a#0,RANGEDEL-b#inf,RANGEDEL
65-
ranges: #0,DEL-#0,DEL
6659

6760
load
6861
a.SET.0:
6962
Span: a-b:{(#0,RANGEDEL)}
7063
----
7164
1: a#0,RANGEDEL-b#inf,RANGEDEL
7265
points: a#0,RANGEDEL-b#inf,RANGEDEL
73-
ranges: #0,DEL-#0,DEL
7466

7567
load
7668
a.SET.0:
7769
Span: a-b:{(#0,RANGEDEL)}
7870
----
7971
1: a#0,RANGEDEL-b#inf,RANGEDEL
8072
points: a#0,RANGEDEL-b#inf,RANGEDEL
81-
ranges: #0,DEL-#0,DEL
8273

8374
load
8475
b.SET.0:
8576
Span: a-b:{(#0,RANGEDEL)}
8677
----
8778
1: a#0,RANGEDEL-b#0,SET
8879
points: a#0,RANGEDEL-b#0,SET
89-
ranges: #0,DEL-#0,DEL
9080

9181
# Loading tables at an unsupported table format results in an error.
9282
# Write a table at version 15 (Pebble,v4) into a DB at version 14 (Pebble,v3).

0 commit comments

Comments
 (0)