Skip to content

Commit 26a4f68

Browse files
committed
db: disable writing to value blocks if DisableSeparationBySuffix is true
Make sure this field, which has been moved from SpanPolicy to ValueStoragePolicy, is read for the DisableValueBlocks option in the sst writer.
1 parent 6d69292 commit 26a4f68

File tree

8 files changed

+159
-84
lines changed

8 files changed

+159
-84
lines changed

compaction.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3479,16 +3479,11 @@ func (d *DB) compactAndWrite(
34793479
writerOpts.Compression = block.FastestCompression
34803480
}
34813481
vSep := valueSeparation
3482-
switch spanPolicy.ValueStoragePolicy.PolicyAdjustment {
3483-
case UseDefaultValueStorage:
3484-
// No change to value separation.
3485-
case NoValueSeparation:
3482+
if spanPolicy.ValueStoragePolicy.DisableBlobSeparation {
34863483
vSep = valsep.NeverSeparateValues{}
3487-
case OverrideValueStorage:
3488-
// This span of keyspace is more tolerant of latency, so set a more
3489-
// aggressive value separation policy for this output.
3484+
} else if spanPolicy.ValueStoragePolicy.ContainsOverrides() {
34903485
vSep.SetNextOutputConfig(valsep.ValueSeparationOutputConfig{
3491-
MinimumSize: spanPolicy.ValueStoragePolicy.MinimumSize,
3486+
MinimumSize: spanPolicy.ValueStoragePolicy.OverrideBlobSeparationMinimumSize,
34923487
DisableValueSeparationBySuffix: spanPolicy.ValueStoragePolicy.DisableSeparationBySuffix,
34933488
})
34943489
}

compaction_test.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,24 +1530,18 @@ func runCompactionTest(
15301530
if len(parts) != 1 {
15311531
td.Fatalf(t, "expected disable-separation-by-suffix with no value, got: %s", arg)
15321532
}
1533-
if policy.ValueStoragePolicy.PolicyAdjustment == NoValueSeparation {
1534-
td.Fatalf(t, "conflicting value storage policies for span: %s", line)
1535-
}
1536-
policy.ValueStoragePolicy.PolicyAdjustment = OverrideValueStorage
15371533
policy.ValueStoragePolicy.DisableSeparationBySuffix = true
15381534
case "val-sep-minimum-size":
15391535
if len(parts) != 2 {
15401536
td.Fatalf(t, "expected val-sep-minimum-size=<size>, got: %s", arg)
15411537
}
15421538
size, err := strconv.ParseUint(parts[1], 10, 64)
15431539
if err != nil {
1544-
td.Fatalf(t, "parsing value-minimum-size: %s", err)
1540+
td.Fatalf(t, "parsing val-sep-minimum-size: %s", err)
15451541
}
1546-
policy.ValueStoragePolicy.MinimumSize = int(size)
1542+
policy.ValueStoragePolicy.OverrideBlobSeparationMinimumSize = int(size)
15471543
if size == 0 {
1548-
policy.ValueStoragePolicy.PolicyAdjustment = NoValueSeparation
1549-
} else if int(size) != d.opts.Experimental.ValueSeparationPolicy().MinimumSize {
1550-
policy.ValueStoragePolicy.PolicyAdjustment = OverrideValueStorage
1544+
policy.ValueStoragePolicy.DisableBlobSeparation = true
15511545
}
15521546
default:
15531547
td.Fatalf(t, "unknown span policy arg: %s", arg)

compaction_value_separation.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,17 @@ func shouldWriteBlobFiles(
137137
// blob files so values are stored according to the current policy.
138138
return true, 0
139139
}
140-
switch spanPolicy.ValueStoragePolicy.PolicyAdjustment {
141-
case UseDefaultValueStorage:
142-
// Use the global policy.
143-
case OverrideValueStorage:
144-
expectedMinSize = spanPolicy.ValueStoragePolicy.MinimumSize
140+
if spanPolicy.ValueStoragePolicy.DisableBlobSeparation {
141+
expectedMinSize = 0
142+
} else if spanPolicy.ValueStoragePolicy.ContainsOverrides() {
143+
expectedMinSize = spanPolicy.ValueStoragePolicy.OverrideBlobSeparationMinimumSize
145144
if expectedMinSize == 0 {
146145
// A 0 minimum value size on the span policy indicates the field
147146
// was unset, but other parts of value separation are being
148147
// overridden. Use the default min size.
149148
expectedMinSize = policy.MinimumSize
150149
}
151150
expectedValSepBySuffixDisabled = spanPolicy.ValueStoragePolicy.DisableSeparationBySuffix
152-
case NoValueSeparation:
153-
expectedMinSize = 0
154151
}
155152
}
156153

options.go

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,70 +1297,63 @@ func (p SpanPolicy) String() string {
12971297
if p.ValueStoragePolicy.DisableSeparationBySuffix {
12981298
sb.WriteString("disable-value-separation-by-suffix,")
12991299
}
1300-
switch p.ValueStoragePolicy.PolicyAdjustment {
1301-
case NoValueSeparation:
1302-
sb.WriteString("no-value-separation,")
1303-
case OverrideValueStorage:
1304-
sb.WriteString("override,")
1300+
if p.ValueStoragePolicy.DisableBlobSeparation {
1301+
sb.WriteString("no-blob-value-separation,")
1302+
}
1303+
if p.ValueStoragePolicy.OverrideBlobSeparationMinimumSize > 0 {
1304+
sb.WriteString("override-value-separation-min-size")
13051305
}
13061306
return strings.TrimSuffix(sb.String(), ",")
13071307
}
13081308

13091309
// ValueStoragePolicyAdjustment is used to determine where to store the values for
1310-
// KVs. If the PolicyAdjustment specified is OverrideValueStorage, the remaining fields
1311-
// are used to override the global configuration for value separation.
1310+
// KVs, overriding global policies. Values can be configured to be stored in-place,
1311+
// in value blocks, or in blob files.
13121312
type ValueStoragePolicyAdjustment struct {
1313-
// PolicyAdjustment specifies the policy adjustment to apply.
1314-
PolicyAdjustment ValueStoragePolicyAdjustmentType
1315-
1316-
// Remaining fields are ignored, unless the PolicyAdjustment is OverrideValueStorage.
1317-
13181313
// DisableSeparationBySuffix disables discriminating KVs depending on
13191314
// suffix.
13201315
//
13211316
// Among a set of keys with the same prefix, Pebble's default heuristics
13221317
// optimize access to the KV with the smallest suffix. This is useful for MVCC
13231318
// keys (where the smallest suffix is the latest version), but should be
13241319
// disabled for keys where the suffix does not correspond to a version.
1320+
// See sstable.IsLikelyMVCCGarbage for the exact criteria we use to
1321+
// determine whether a value is likely MVCC garbage.
1322+
//
1323+
// If separation by suffix is enabled, KVs with older suffix values will be
1324+
// written according to the following rules:
1325+
// - If the value is empty, no separation is performed.
1326+
// - If blob separation is enabled the value will be separated into a blob
1327+
// file even if its size is smaller than the minimum value size.
1328+
// - If blob separation is disabled, the value will be written to a value
1329+
// block within the sstable.
13251330
DisableSeparationBySuffix bool
1326-
// MinimumSize is the minimum size of the value.
1327-
MinimumSize int
1328-
}
13291331

1330-
// ValueStoragePolicyAdjustmentType is a hint used to determine where to store the
1331-
// values for KVs.
1332-
type ValueStoragePolicyAdjustmentType uint8
1332+
// DisableBlobSeparation disables separating values into blob files.
1333+
DisableBlobSeparation bool
13331334

1334-
const (
1335-
// UseDefaultValueStorage is the default value; Pebble will respect global
1336-
// configuration for value separation.
1337-
UseDefaultValueStorage ValueStoragePolicyAdjustmentType = iota
1338-
1339-
// NoValueSeparation indicates Pebble should prefer storing values
1340-
// in-place.
1341-
NoValueSeparation
1342-
1343-
// OverrideValueStorage indicates that value separation thresholds (see
1344-
// valsep.ValueSeparationOutputConfig) for this key range are being
1345-
// overridden from a SpanPolicy. If the global Options enable value
1346-
// separation, Pebble will separate values under the OverrideValueStorage
1347-
// policy even if they do not meet the minimum size threshold of the
1348-
// global Options' ValueSeparationPolicy.
1349-
OverrideValueStorage
1350-
)
1335+
// OverrideBlobSeparationMinimumSize overrides the minimum size required
1336+
// for value separation into a blob file. Note that value separation must
1337+
// be enabled globally for this to take effect.
1338+
OverrideBlobSeparationMinimumSize int
1339+
}
1340+
1341+
func (vsp *ValueStoragePolicyAdjustment) ContainsOverrides() bool {
1342+
return vsp.OverrideBlobSeparationMinimumSize > 0 || vsp.DisableSeparationBySuffix
1343+
}
13511344

13521345
// ValueStorageLatencyTolerant is the suggested ValueStoragePolicyAdjustment
13531346
// to use for key ranges that can tolerate higher value retrieval
13541347
// latency.
13551348
var ValueStorageLatencyTolerant = ValueStoragePolicyAdjustment{
1356-
PolicyAdjustment: OverrideValueStorage,
1357-
MinimumSize: 10,
1349+
OverrideBlobSeparationMinimumSize: 10,
13581350
}
13591351

13601352
// ValueStorageLowReadLatency is the suggested ValueStoragePolicyAdjustment
13611353
// to use for key ranges that require low value retrieval latency.
13621354
var ValueStorageLowReadLatency = ValueStoragePolicyAdjustment{
1363-
PolicyAdjustment: NoValueSeparation,
1355+
DisableBlobSeparation: true,
1356+
DisableSeparationBySuffix: true,
13641357
}
13651358

13661359
// SpanPolicyFunc is used to determine the SpanPolicy for a key region.

sstable/properties.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ type Properties struct {
125125
// The minimum size a value must be to be separated into a blob file during writing.
126126
ValueSeparationMinSize uint64 `prop:"pebble.value-separation.min-size"`
127127
// ValueSeparationBySuffixDisabled indicates if special value separation rules were
128-
// applied based on the KV suffix when writing. Pebble attempts to optimize writing of
129-
// MVCC garbage values into blob files, which are recognized by the key suffix.
128+
// applied based on the KV suffix when writing blob files. Pebble attempts to optimize
129+
// separating MVCC garbage, which are recognized by the key suffix. Note that this
130+
// value corresponds only for blob file writing and not value blocks.
130131
ValueSeparationBySuffixDisabled bool `prop:"pebble.value-separation.by-suffix.disabled"`
131132
// User collected properties. Currently, we only use them to store block
132133
// properties aggregated at the table level.

testdata/compaction/mvcc_garbage_blob

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ flush-log
6767

6868
# Another test with the same value separation config, but this time we set a span
6969
# policy for the span y-zz that disables value separation by suffix. This should
70-
# prevent MVCC garbage from being written to blob files.
70+
# prevent MVCC garbage from being separeted (both into blob files and value blocks).
7171

7272
define value-separation=(enabled, min-size=5, max-ref-depth=3, garbage-ratios=1.0:1.0)
7373
----
@@ -127,3 +127,99 @@ pebble.compression_stats: None:234
127127
pebble.value-separation.min-size: 5
128128
pebble.value-separation.by-suffix.disabled: true
129129
obsolete-key: hex:00
130+
131+
define value-separation=(enabled, min-size=5, max-ref-depth=3, garbage-ratios=1.0:1.0)
132+
----
133+
134+
set-span-policies
135+
a,c val-sep-minimum-size=0
136+
----
137+
138+
139+
batch
140+
set a@2 a2
141+
set b@5 b5
142+
del b@4
143+
set b@3 bat3
144+
set b@2 bat2
145+
del b@1
146+
set b@1 bat1
147+
set b@0 bat0
148+
----
149+
150+
# Although we've disabled value separation into blob files, writing to
151+
# value blocks should still be enabled.
152+
flush
153+
----
154+
L0.0:
155+
000005:[a@2#10,SET-b@0#17,SET] seqnums:[10-17] points:[a@2#10,SET-b@0#17,SET] size:880
156+
157+
sstable-properties file=000005
158+
----
159+
rocksdb.num.entries: 7
160+
rocksdb.raw.key.size: 77
161+
rocksdb.raw.value.size: 20
162+
pebble.raw.point-tombstone.key.size: 3
163+
rocksdb.deleted.keys: 1
164+
rocksdb.num.range-deletions: 0
165+
pebble.value-blocks.size: 25
166+
rocksdb.num.data.blocks: 1
167+
rocksdb.comparator: pebble.internal.testkeys
168+
rocksdb.data.size: 175
169+
rocksdb.filter.size: 0
170+
rocksdb.index.size: 36
171+
rocksdb.block.based.table.index.type: 0
172+
pebble.colblk.schema: DefaultKeySchema(pebble.internal.testkeys,16)
173+
rocksdb.merge.operator: pebble.concatenate
174+
rocksdb.merge.operands: 0
175+
pebble.num.value-blocks: 1
176+
pebble.num.values.in.value-blocks: 3
177+
rocksdb.property.collectors: [obsolete-key]
178+
rocksdb.compression: Snappy
179+
pebble.compression_stats: None:221
180+
obsolete-key: hex:00
181+
182+
batch
183+
set a@2 a2
184+
set b@5 b5
185+
del b@4
186+
set b@3 bat3
187+
set b@2 bat2
188+
del b@1
189+
set b@1 bat1
190+
set b@0 bat0
191+
----
192+
193+
# Disabling value separation by suffix should also disable writing to value blocks.
194+
set-span-policies
195+
a,c val-sep-minimum-size=0 disable-separation-by-suffix
196+
----
197+
198+
flush
199+
----
200+
L0.1:
201+
000007:[a@2#18,SET-b@0#25,SET] seqnums:[18-25] points:[a@2#18,SET-b@0#25,SET] size:770
202+
L0.0:
203+
000005:[a@2#10,SET-b@0#17,SET] seqnums:[10-17] points:[a@2#10,SET-b@0#17,SET] size:880
204+
205+
sstable-properties file=000007
206+
----
207+
rocksdb.num.entries: 7
208+
rocksdb.raw.key.size: 77
209+
rocksdb.raw.value.size: 20
210+
pebble.raw.point-tombstone.key.size: 3
211+
rocksdb.deleted.keys: 1
212+
rocksdb.num.range-deletions: 0
213+
rocksdb.num.data.blocks: 1
214+
rocksdb.comparator: pebble.internal.testkeys
215+
rocksdb.data.size: 157
216+
rocksdb.filter.size: 0
217+
rocksdb.index.size: 36
218+
rocksdb.block.based.table.index.type: 0
219+
pebble.colblk.schema: DefaultKeySchema(pebble.internal.testkeys,16)
220+
rocksdb.merge.operator: pebble.concatenate
221+
rocksdb.merge.operands: 0
222+
rocksdb.property.collectors: [obsolete-key]
223+
rocksdb.compression: Snappy
224+
pebble.compression_stats: None:188
225+
obsolete-key: hex:00

testdata/static_span_policy_func

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ a b c d e f g
66
a -> until d
77
b -> until d
88
c -> until d
9-
d -> no-value-separation until f
10-
e -> no-value-separation until f
9+
d -> disable-value-separation-by-suffix,no-blob-value-separation until f
10+
e -> disable-value-separation-by-suffix,no-blob-value-separation until f
1111
f -> none
1212
g -> none
1313

@@ -17,11 +17,11 @@ g -> none
1717
test a-z:lowlatency
1818
a b c d e z
1919
----
20-
a -> no-value-separation until z
21-
b -> no-value-separation until z
22-
c -> no-value-separation until z
23-
d -> no-value-separation until z
24-
e -> no-value-separation until z
20+
a -> disable-value-separation-by-suffix,no-blob-value-separation until z
21+
b -> disable-value-separation-by-suffix,no-blob-value-separation until z
22+
c -> disable-value-separation-by-suffix,no-blob-value-separation until z
23+
d -> disable-value-separation-by-suffix,no-blob-value-separation until z
24+
e -> disable-value-separation-by-suffix,no-blob-value-separation until z
2525
z -> none
2626

2727
# Abutting policies.
@@ -30,12 +30,12 @@ test b-d:lowlatency d-f:latencytolerant f-h:lowlatency
3030
a b c d e f g h i z
3131
----
3232
a -> until b
33-
b -> no-value-separation until d
34-
c -> no-value-separation until d
35-
d -> override until f
36-
e -> override until f
37-
f -> no-value-separation until h
38-
g -> no-value-separation until h
33+
b -> disable-value-separation-by-suffix,no-blob-value-separation until d
34+
c -> disable-value-separation-by-suffix,no-blob-value-separation until d
35+
d -> override-value-separation-min-size until f
36+
e -> override-value-separation-min-size until f
37+
f -> disable-value-separation-by-suffix,no-blob-value-separation until h
38+
g -> disable-value-separation-by-suffix,no-blob-value-separation until h
3939
h -> none
4040
i -> none
4141
z -> none
@@ -46,14 +46,14 @@ test b-d:lowlatency h-j:latencytolerant
4646
a b c d e f g h i j k l
4747
----
4848
a -> until b
49-
b -> no-value-separation until d
50-
c -> no-value-separation until d
49+
b -> disable-value-separation-by-suffix,no-blob-value-separation until d
50+
c -> disable-value-separation-by-suffix,no-blob-value-separation until d
5151
d -> until h
5252
e -> until h
5353
f -> until h
5454
g -> until h
55-
h -> override until j
56-
i -> override until j
55+
h -> override-value-separation-min-size until j
56+
i -> override-value-separation-min-size until j
5757
j -> none
5858
k -> none
5959
l -> none

valsep/value_separator.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,7 @@ func NewWriteNewBlobFiles(
163163
// SetNextOutputConfig implements the ValueSeparation interface.
164164
func (vs *ValueSeparator) SetNextOutputConfig(config ValueSeparationOutputConfig) {
165165
if config.MinimumSize == 0 {
166-
// This indicates that MinimumSize was unset, so fall back
167-
// to the global minimum size.
166+
// No override, so fall back to the global minimum size.
168167
config.MinimumSize = vs.globalConfig.MinimumSize
169168
}
170169
vs.currentConfig = config

0 commit comments

Comments
 (0)