@@ -259,44 +259,49 @@ func ingestLoad1(
259
259
cacheHandle * cache.Handle ,
260
260
tableNum base.TableNum ,
261
261
rangeKeyValidator rangeKeyIngestValidator ,
262
- ) (meta * manifest.TableMetadata , lastRangeKey keyspan.Span , err error ) {
262
+ ) (
263
+ meta * manifest.TableMetadata ,
264
+ lastRangeKey keyspan.Span ,
265
+ blockReadStats base.BlockReadStats ,
266
+ err error ,
267
+ ) {
263
268
o := opts .MakeReaderOptions ()
264
269
o .CacheOpts = sstableinternal.CacheOptions {
265
270
CacheHandle : cacheHandle ,
266
271
FileNum : base .PhysicalTableDiskFileNum (tableNum ),
267
272
}
268
273
r , err := sstable .NewReader (ctx , readable , o )
269
274
if err != nil {
270
- return nil , keyspan.Span {}, errors .CombineErrors (err , readable .Close ())
275
+ return nil , keyspan.Span {}, base. BlockReadStats {}, errors .CombineErrors (err , readable .Close ())
271
276
}
272
277
defer func () { _ = r .Close () }()
273
278
274
279
// Avoid ingesting tables with format versions this DB doesn't support.
275
280
tf , err := r .TableFormat ()
276
281
if err != nil {
277
- return nil , keyspan.Span {}, err
282
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
278
283
}
279
284
if tf < fmv .MinTableFormat () || tf > fmv .MaxTableFormat () {
280
- return nil , keyspan.Span {}, errors .Newf (
285
+ return nil , keyspan.Span {}, base. BlockReadStats {}, errors .Newf (
281
286
"pebble: table format %s is not within range supported at DB format major version %d, (%s,%s)" ,
282
287
tf , fmv , fmv .MinTableFormat (), fmv .MaxTableFormat (),
283
288
)
284
289
}
285
290
286
291
if r .Attributes .Has (sstable .AttributeBlobValues ) {
287
- return nil , keyspan.Span {}, errors .Newf (
292
+ return nil , keyspan.Span {}, base. BlockReadStats {}, errors .Newf (
288
293
"pebble: ingesting tables with blob references is not supported" )
289
294
}
290
295
291
296
props , err := r .ReadPropertiesBlock (ctx , nil /* buffer pool */ )
292
297
if err != nil {
293
- return nil , keyspan.Span {}, err
298
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
294
299
}
295
300
296
301
// If this is a columnar block, read key schema name from properties block.
297
302
if tf .BlockColumnar () {
298
303
if _ , ok := opts .KeySchemas [props .KeySchemaName ]; ! ok {
299
- return nil , keyspan.Span {}, errors .Newf (
304
+ return nil , keyspan.Span {}, base. BlockReadStats {}, errors .Newf (
300
305
"pebble: table uses key schema %q unknown to the database" ,
301
306
props .KeySchemaName )
302
307
}
@@ -319,55 +324,71 @@ func ingestLoad1(
319
324
// calculating stats before we can remove the original link.
320
325
maybeSetStatsFromProperties (meta .PhysicalMeta (), & props , opts .Logger )
321
326
327
+ var iterStats base.InternalIteratorStats
328
+ env := sstable.ReadEnv {
329
+ Block : block.ReadEnv {
330
+ Stats : & iterStats ,
331
+ },
332
+ }
322
333
{
323
- iter , err := r .NewIter (sstable .NoTransforms , nil /* lower */ , nil /* upper */ , sstable .AssertNoBlobHandles )
334
+ iterOpts := sstable.IterOptions {
335
+ Lower : nil ,
336
+ Upper : nil ,
337
+ Transforms : sstable .NoTransforms ,
338
+ Filterer : nil ,
339
+ FilterBlockSizeLimit : sstable .AlwaysUseFilterBlock ,
340
+ Env : env ,
341
+ ReaderProvider : sstable .MakeTrivialReaderProvider (r ),
342
+ BlobContext : sstable .AssertNoBlobHandles ,
343
+ }
344
+ iter , err := r .NewPointIter (ctx , iterOpts )
324
345
if err != nil {
325
- return nil , keyspan.Span {}, err
346
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
326
347
}
327
348
defer func () { _ = iter .Close () }()
328
349
var smallest InternalKey
329
350
if kv := iter .First (); kv != nil {
330
351
if err := ingestValidateKey (opts , & kv .K ); err != nil {
331
- return nil , keyspan.Span {}, err
352
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
332
353
}
333
354
smallest = kv .K .Clone ()
334
355
}
335
356
if err := iter .Error (); err != nil {
336
- return nil , keyspan.Span {}, err
357
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
337
358
}
338
359
if kv := iter .Last (); kv != nil {
339
360
if err := ingestValidateKey (opts , & kv .K ); err != nil {
340
- return nil , keyspan.Span {}, err
361
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
341
362
}
342
363
meta .ExtendPointKeyBounds (opts .Comparer .Compare , smallest , kv .K .Clone ())
343
364
}
344
365
if err := iter .Error (); err != nil {
345
- return nil , keyspan.Span {}, err
366
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
346
367
}
347
368
}
348
369
349
- iter , err := r .NewRawRangeDelIter (ctx , sstable .NoFragmentTransforms , sstable . NoReadEnv )
370
+ iter , err := r .NewRawRangeDelIter (ctx , sstable .NoFragmentTransforms , env )
350
371
if err != nil {
351
- return nil , keyspan.Span {}, err
372
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
352
373
}
353
374
if iter != nil {
354
375
defer iter .Close ()
355
376
var smallest InternalKey
356
377
if s , err := iter .First (); err != nil {
357
- return nil , keyspan.Span {}, err
378
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
358
379
} else if s != nil {
359
380
key := s .SmallestKey ()
360
381
if err := ingestValidateKey (opts , & key ); err != nil {
361
- return nil , keyspan.Span {}, err
382
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
362
383
}
363
384
smallest = key .Clone ()
364
385
}
365
386
if s , err := iter .Last (); err != nil {
366
- return nil , keyspan.Span {}, err
387
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
367
388
} else if s != nil {
368
389
k := s .SmallestKey ()
369
390
if err := ingestValidateKey (opts , & k ); err != nil {
370
- return nil , keyspan.Span {}, err
391
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
371
392
}
372
393
largest := s .LargestKey ().Clone ()
373
394
meta .ExtendPointKeyBounds (opts .Comparer .Compare , smallest , largest )
@@ -376,34 +397,34 @@ func ingestLoad1(
376
397
377
398
// Update the range-key bounds for the table.
378
399
{
379
- iter , err := r .NewRawRangeKeyIter (ctx , sstable .NoFragmentTransforms , sstable . NoReadEnv )
400
+ iter , err := r .NewRawRangeKeyIter (ctx , sstable .NoFragmentTransforms , env )
380
401
if err != nil {
381
- return nil , keyspan.Span {}, err
402
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
382
403
}
383
404
if iter != nil {
384
405
defer iter .Close ()
385
406
var smallest InternalKey
386
407
if s , err := iter .First (); err != nil {
387
- return nil , keyspan.Span {}, err
408
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
388
409
} else if s != nil {
389
410
key := s .SmallestKey ()
390
411
if err := ingestValidateKey (opts , & key ); err != nil {
391
- return nil , keyspan.Span {}, err
412
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
392
413
}
393
414
smallest = key .Clone ()
394
415
// Range keys need some additional validation as we need to ensure they
395
416
// defragment cleanly with the lastRangeKey from the previous file.
396
417
if err := rangeKeyValidator .Validate (s ); err != nil {
397
- return nil , keyspan.Span {}, err
418
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
398
419
}
399
420
}
400
421
lastRangeKey = keyspan.Span {}
401
422
if s , err := iter .Last (); err != nil {
402
- return nil , keyspan.Span {}, err
423
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
403
424
} else if s != nil {
404
425
k := s .SmallestKey ()
405
426
if err := ingestValidateKey (opts , & k ); err != nil {
406
- return nil , keyspan.Span {}, err
427
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
407
428
}
408
429
// As range keys are fragmented, the end key of the last range key in
409
430
// the table provides the upper bound for the table.
@@ -413,27 +434,27 @@ func ingestLoad1(
413
434
} else {
414
435
// s == nil.
415
436
if err := rangeKeyValidator .Validate (nil /* nextFileSmallestKey */ ); err != nil {
416
- return nil , keyspan.Span {}, err
437
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
417
438
}
418
439
}
419
440
} else {
420
441
if err := rangeKeyValidator .Validate (nil /* nextFileSmallestKey */ ); err != nil {
421
- return nil , keyspan.Span {}, err
442
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
422
443
}
423
444
lastRangeKey = keyspan.Span {}
424
445
}
425
446
}
426
447
427
448
if ! meta .HasPointKeys && ! meta .HasRangeKeys {
428
- return nil , keyspan.Span {}, nil
449
+ return nil , keyspan.Span {}, base. BlockReadStats {}, nil
429
450
}
430
451
431
452
// Sanity check that the various bounds on the file were set consistently.
432
453
if err := meta .Validate (opts .Comparer .Compare , opts .Comparer .FormatKey ); err != nil {
433
- return nil , keyspan.Span {}, err
454
+ return nil , keyspan.Span {}, base. BlockReadStats {}, err
434
455
}
435
456
436
- return meta , lastRangeKey , nil
457
+ return meta , lastRangeKey , iterStats . TotalBlockReads (), nil
437
458
}
438
459
439
460
type ingestLoadResult struct {
@@ -442,6 +463,7 @@ type ingestLoadResult struct {
442
463
external []ingestExternalMeta
443
464
444
465
externalFilesHaveLevel bool
466
+ blockReadStats base.BlockReadStats
445
467
}
446
468
447
469
type ingestLocalMeta struct {
@@ -485,6 +507,7 @@ func ingestLoad(
485
507
var result ingestLoadResult
486
508
result .local = make ([]ingestLocalMeta , 0 , len (paths ))
487
509
var lastRangeKey keyspan.Span
510
+ var blockReadStats base.BlockReadStats
488
511
// NB: we disable range key boundary assertions if we have shared or external files
489
512
// present in this ingestion. This is because a suffixed range key in a local file
490
513
// can possibly defragment with a suffixed range key in a shared or external file.
@@ -508,7 +531,7 @@ func ingestLoad(
508
531
if ! shouldDisableRangeKeyChecks {
509
532
rangeKeyValidator = validateSuffixedBoundaries (opts .Comparer , lastRangeKey )
510
533
}
511
- m , lastRangeKey , err = ingestLoad1 (ctx , opts , fmv , readable , cacheHandle , localFileNums [i ], rangeKeyValidator )
534
+ m , lastRangeKey , blockReadStats , err = ingestLoad1 (ctx , opts , fmv , readable , cacheHandle , localFileNums [i ], rangeKeyValidator )
512
535
if err != nil {
513
536
return ingestLoadResult {}, err
514
537
}
@@ -517,6 +540,7 @@ func ingestLoad(
517
540
TableMetadata : m ,
518
541
path : paths [i ],
519
542
})
543
+ result .blockReadStats = blockReadStats
520
544
}
521
545
}
522
546
@@ -1455,7 +1479,8 @@ func (d *DB) ingest(ctx context.Context, args ingestArgs) (IngestOperationStats,
1455
1479
1456
1480
// Load the metadata for all the files being ingested. This step detects
1457
1481
// and elides empty sstables.
1458
- loadResult , err := ingestLoad (ctx , d .opts , d .FormatMajorVersion (), paths , shared , external , d .cacheHandle , pendingOutputs )
1482
+ loadResult , err := ingestLoad (ctx , d .opts , d .FormatMajorVersion (), paths , shared , external ,
1483
+ d .cacheHandle , pendingOutputs )
1459
1484
if err != nil {
1460
1485
return IngestOperationStats {}, err
1461
1486
}
@@ -1734,6 +1759,8 @@ func (d *DB) ingest(ctx context.Context, args ingestArgs) (IngestOperationStats,
1734
1759
flushable : asFlushable ,
1735
1760
WaitFlushDuration : waitFlushDuration ,
1736
1761
ManifestUpdateDuration : manifestUpdateDuration ,
1762
+ BlockReadDuration : loadResult .blockReadStats .BlockReadDuration ,
1763
+ BlockReadBytes : loadResult .blockReadStats .BlockBytes - loadResult .blockReadStats .BlockBytesInCache ,
1737
1764
}
1738
1765
if len (loadResult .local ) > 0 {
1739
1766
info .GlobalSeqNum = loadResult .local [0 ].SmallestSeqNum
@@ -1924,12 +1951,11 @@ func (d *DB) ingestApply(
1924
1951
}
1925
1952
var metrics levelMetricsDelta
1926
1953
1927
- manifestUpdateStart := crtime .NowMono ()
1928
1954
// Determine the target level inside UpdateVersionLocked. This prevents two
1929
1955
// concurrent ingestion jobs from using the same version to determine the
1930
1956
// target level, and also provides serialization with concurrent compaction
1931
1957
// and flush jobs.
1932
- err := d .mu .versions .UpdateVersionLocked (func () (versionUpdate , error ) {
1958
+ manifestUpdateDuration , err := d .mu .versions .UpdateVersionLocked (func () (versionUpdate , error ) {
1933
1959
if mut != nil {
1934
1960
// Unref the mutable memtable to allows its flush to proceed. Now that we've
1935
1961
// acquired the manifest lock, we can be certain that if the mutable
@@ -2174,8 +2200,6 @@ func (d *DB) ingestApply(
2174
2200
if err != nil {
2175
2201
return nil , 0 , err
2176
2202
}
2177
- manifestUpdateDuration := manifestUpdateStart .Elapsed ()
2178
-
2179
2203
// Check for any EventuallyFileOnlySnapshots that could be watching for
2180
2204
// an excise on this span. There should be none as the
2181
2205
// computePossibleOverlaps steps should have forced these EFOS to transition
@@ -2220,6 +2244,7 @@ func (d *DB) ingestApply(
2220
2244
}
2221
2245
}
2222
2246
d .maybeValidateSSTablesLocked (toValidate )
2247
+
2223
2248
return ve , manifestUpdateDuration , nil
2224
2249
}
2225
2250
0 commit comments