@@ -297,32 +297,38 @@ class TDummyScan : public TActor<TDummyScan>, public NTable::IScan {
297
297
if (seq && Abort == EAbort::None)
298
298
return EScan::Final;
299
299
300
- lead.To (Scheme->Tags (), { }, NTable::ESeek::Lower);
300
+ lead.To (Scheme->Tags (), LeadKey, NTable::ESeek::Lower);
301
+ if (LeadKey) {
302
+ ExpectedRowId = LeadKey[0 ].AsValue <ui64>();
303
+ }
301
304
return EScan::Feed;
302
305
}
303
306
304
307
EScan Feed (TArrayRef<const TCell> key, const TRow &) noexcept override
305
308
{
306
- UNIT_ASSERT_VALUES_EQUAL (key[0 ].AsValue <ui64>(), ExpectedRowId);
309
+ Y_ABORT_UNLESS (key[0 ].AsValue <ui64>() == ExpectedRowId);
307
310
++ExpectedRowId;
308
311
++StoredRows;
309
312
return EScan::Feed;
310
313
}
311
314
312
315
TAutoPtr<IDestructable> Finish (EAbort abort) noexcept override
313
316
{
314
- UNIT_ASSERT_VALUES_EQUAL ((int )Abort, (int )abort);
317
+ Y_ABORT_UNLESS ((int )Abort == (int )abort);
315
318
316
319
auto ctx = ActorContext ();
317
320
if (abort == EAbort::None) {
318
- UNIT_ASSERT_VALUES_EQUAL (ExpectedRows, StoredRows);
321
+ Y_ABORT_UNLESS (ExpectedRows == StoredRows);
319
322
}
320
323
321
324
Die (ctx);
322
325
323
326
return new TDummyResult (StoredRows, ExpectedRows);
324
327
}
325
328
329
+ public:
330
+ TArrayRef<const TCell> LeadKey;
331
+
326
332
private:
327
333
TActorId Tablet;
328
334
IDriver *Driver = nullptr ;
@@ -369,6 +375,9 @@ struct TEvTestFlatTablet {
369
375
NTable::EAbort Abort;
370
376
const TRowVersion ReadVersion;
371
377
const ui32 ExpectRows = 0 ;
378
+
379
+ std::optional<std::pair<ui64, ui64>> ReadAhead;
380
+ TArrayRef<const TCell> LeadKey;
372
381
};
373
382
struct TEvStartQueuedScan : public TEventLocal <TEvStartQueuedScan, EvStartQueuedScan> {};
374
383
struct TEvMakeScanSnapshot : public TEventLocal <TEvMakeScanSnapshot, EvMakeScanSnapshot> {};
@@ -442,13 +451,17 @@ class TTestFlatTablet : public TActor<TTestFlatTablet>, public TTabletExecutedFl
442
451
auto abort = ev->Get ()->Abort ;
443
452
auto rows = abort != NTable::EAbort::None ? 0 : ev->Get ()->ExpectRows ;
444
453
Scan = new TDummyScan (SelfId (), postpone, abort, rows);
454
+ Scan->LeadKey = ev->Get ()->LeadKey ;
445
455
TScanOptions options;
446
456
if (snap) {
447
457
Y_ABORT_UNLESS (ev->Get ()->ReadVersion .IsMax (), " Cannot combine multiple snapshot techniques" );
448
458
options.SetSnapshotId (snap);
449
459
} else if (!ev->Get ()->ReadVersion .IsMax ()) {
450
460
options.SetSnapshotRowVersion (ev->Get ()->ReadVersion );
451
461
}
462
+ if (auto readAhead = ev->Get ()->ReadAhead ) {
463
+ options.SetReadAhead (readAhead->first , readAhead->second );
464
+ }
452
465
ScanTaskId = Executor ()->QueueScan (TRowsModel::TableId, Scan, ScanCookie, options);
453
466
}
454
467
@@ -5074,7 +5087,14 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorIndexLoading) {
5074
5087
}
5075
5088
};
5076
5089
5077
- Y_UNIT_TEST (TestPrechargeAndSeek_FlatIndex) {
5090
+ void ZeroSharedCache (TMyEnvBase &env) {
5091
+ env.Env .GetMemObserver ()->NotifyStat ({1 , 1 , 1 });
5092
+ TDispatchOptions options;
5093
+ options.FinalEvents .push_back (TDispatchOptions::TFinalEventCondition (NSharedCache::EvMem, 1 ));
5094
+ env->DispatchEvents (options);
5095
+ }
5096
+
5097
+ Y_UNIT_TEST (PrechargeAndSeek_FlatIndex) {
5078
5098
TMyEnvBase env;
5079
5099
TRowsModel rows;
5080
5100
@@ -5119,7 +5139,7 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorIndexLoading) {
5119
5139
env.SendSync (new TEvents::TEvPoison, false , true );
5120
5140
}
5121
5141
5122
- Y_UNIT_TEST (TestPrechargeAndSeek_BTreeIndex ) {
5142
+ Y_UNIT_TEST (PrechargeAndSeek_BTreeIndex ) {
5123
5143
TMyEnvBase env;
5124
5144
TRowsModel rows;
5125
5145
@@ -5164,6 +5184,193 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorIndexLoading) {
5164
5184
env.SendSync (new TEvents::TEvPoison, false , true );
5165
5185
}
5166
5186
5187
+ Y_UNIT_TEST (Scan_BTreeIndex) {
5188
+ TMyEnvBase env;
5189
+ TRowsModel rows;
5190
+ const ui32 rowsCount = 1024 ;
5191
+
5192
+ auto &appData = env->GetAppData ();
5193
+ appData.FeatureFlags .SetEnableLocalDBBtreeIndex (true );
5194
+ appData.FeatureFlags .SetEnableLocalDBFlatIndex (false );
5195
+
5196
+ env->SetLogPriority (NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_DEBUG);
5197
+
5198
+ env.FireTablet (env.Edge , env.Tablet , [&env](const TActorId &tablet, TTabletStorageInfo *info) {
5199
+ return new TTestFlatTablet (env.Edge , tablet, info);
5200
+ });
5201
+ env.WaitForWakeUp ();
5202
+ ZeroSharedCache (env);
5203
+
5204
+ env.SendSync (rows.MakeScheme (new TCompactionPolicy (), false ));
5205
+
5206
+ env.SendSync (rows.MakeRows (rowsCount, 10 *1024 ));
5207
+
5208
+ env.SendSync (new NFake::TEvCompact (TRowsModel::TableId));
5209
+ env.WaitFor <NFake::TEvCompacted>();
5210
+
5211
+ { // no read ahead
5212
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5213
+ queueScan->ReadAhead = {1 , 1 };
5214
+ env.SendAsync (std::move (queueScan));
5215
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5216
+ }
5217
+
5218
+ { // small read ahead
5219
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5220
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5221
+ env.SendAsync (std::move (queueScan));
5222
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5223
+ }
5224
+
5225
+ { // infinite read ahead
5226
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5227
+ queueScan->ReadAhead = {Max<ui64>(), Max<ui64>()};
5228
+ env.SendAsync (std::move (queueScan));
5229
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5230
+ }
5231
+
5232
+ for (ui64 leadKey = 1 ; ; leadKey += rowsCount / 10 ) {
5233
+ ui64 expectedRowsCount = rowsCount > leadKey ? rowsCount - leadKey + 1 : 0 ;
5234
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (expectedRowsCount);
5235
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5236
+ TVector<TCell> leadKey_ = {TCell::Make (leadKey)};
5237
+ queueScan->LeadKey = leadKey_;
5238
+ env.SendAsync (std::move (queueScan));
5239
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5240
+ if (!expectedRowsCount) {
5241
+ break ;
5242
+ }
5243
+ }
5244
+
5245
+ // If we didn't crash, then assume the test succeeded
5246
+ env.SendSync (new TEvents::TEvPoison, false , true );
5247
+ }
5248
+
5249
+ Y_UNIT_TEST (Scan_History_BTreeIndex) {
5250
+ TMyEnvBase env;
5251
+ TRowsModel rows;
5252
+ const ui32 rowsCount = 1024 ;
5253
+
5254
+ auto &appData = env->GetAppData ();
5255
+ appData.FeatureFlags .SetEnableLocalDBBtreeIndex (true );
5256
+ appData.FeatureFlags .SetEnableLocalDBFlatIndex (false );
5257
+
5258
+ env->SetLogPriority (NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_DEBUG);
5259
+
5260
+ env.FireTablet (env.Edge , env.Tablet , [&env](const TActorId &tablet, TTabletStorageInfo *info) {
5261
+ return new TTestFlatTablet (env.Edge , tablet, info);
5262
+ });
5263
+ env.WaitForWakeUp ();
5264
+ ZeroSharedCache (env);
5265
+
5266
+ env.SendSync (rows.MakeScheme (new TCompactionPolicy (), false ));
5267
+
5268
+ env.SendSync (rows.RowTo (1 ).VersionTo (TRowVersion (1 , 10 )).MakeRows (rowsCount, 10 *1024 ));
5269
+ env.SendSync (rows.RowTo (1 ).VersionTo (TRowVersion (2 , 20 )).MakeRows (rowsCount, 10 *1024 ));
5270
+
5271
+ env.SendSync (new NFake::TEvCompact (TRowsModel::TableId));
5272
+ env.WaitFor <NFake::TEvCompacted>();
5273
+
5274
+ { // no read ahead
5275
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount, TRowVersion (2 , 0 ));
5276
+ queueScan->ReadAhead = {1 , 1 };
5277
+ env.SendAsync (std::move (queueScan));
5278
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5279
+ }
5280
+
5281
+ { // small read ahead
5282
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount, TRowVersion (2 , 0 ));
5283
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5284
+ env.SendAsync (std::move (queueScan));
5285
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5286
+ }
5287
+
5288
+ { // infinite read ahead
5289
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount, TRowVersion (2 , 0 ));
5290
+ queueScan->ReadAhead = {Max<ui64>(), Max<ui64>()};
5291
+ env.SendAsync (std::move (queueScan));
5292
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5293
+ }
5294
+
5295
+ for (ui64 leadKey = 1 ; ; leadKey += rowsCount / 10 ) {
5296
+ ui64 expectedRowsCount = rowsCount > leadKey ? rowsCount - leadKey + 1 : 0 ;
5297
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (expectedRowsCount, TRowVersion (2 , 0 ));
5298
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5299
+ TVector<TCell> leadKey_ = {TCell::Make (leadKey)};
5300
+ queueScan->LeadKey = leadKey_;
5301
+ env.SendAsync (std::move (queueScan));
5302
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5303
+ if (!expectedRowsCount) {
5304
+ break ;
5305
+ }
5306
+ }
5307
+
5308
+ // If we didn't crash, then assume the test succeeded
5309
+ env.SendSync (new TEvents::TEvPoison, false , true );
5310
+ }
5311
+
5312
+ Y_UNIT_TEST (Scan_Groups_BTreeIndex) {
5313
+ TMyEnvBase env;
5314
+ TRowsModel rows;
5315
+ const ui32 rowsCount = 1024 ;
5316
+
5317
+ auto &appData = env->GetAppData ();
5318
+ appData.FeatureFlags .SetEnableLocalDBBtreeIndex (true );
5319
+ appData.FeatureFlags .SetEnableLocalDBFlatIndex (false );
5320
+
5321
+ env->SetLogPriority (NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_DEBUG);
5322
+
5323
+ env.FireTablet (env.Edge , env.Tablet , [&env](const TActorId &tablet, TTabletStorageInfo *info) {
5324
+ return new TTestFlatTablet (env.Edge , tablet, info);
5325
+ });
5326
+ env.WaitForWakeUp ();
5327
+ ZeroSharedCache (env);
5328
+
5329
+ env.SendSync (rows.MakeScheme (new TCompactionPolicy (), true ));
5330
+
5331
+ env.SendSync (rows.MakeRows (rowsCount, 10 *1024 ));
5332
+
5333
+ env.SendSync (new NFake::TEvCompact (TRowsModel::TableId));
5334
+ env.WaitFor <NFake::TEvCompacted>();
5335
+
5336
+ { // no read ahead
5337
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5338
+ queueScan->ReadAhead = {1 , 1 };
5339
+ env.SendAsync (std::move (queueScan));
5340
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5341
+ }
5342
+
5343
+ { // small read ahead
5344
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5345
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5346
+ env.SendAsync (std::move (queueScan));
5347
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5348
+ }
5349
+
5350
+ { // infinite read ahead
5351
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5352
+ queueScan->ReadAhead = {Max<ui64>(), Max<ui64>()};
5353
+ env.SendAsync (std::move (queueScan));
5354
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5355
+ }
5356
+
5357
+ for (ui64 leadKey = 1 ; ; leadKey += rowsCount / 10 ) {
5358
+ ui64 expectedRowsCount = rowsCount > leadKey ? rowsCount - leadKey + 1 : 0 ;
5359
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (expectedRowsCount);
5360
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5361
+ TVector<TCell> leadKey_ = {TCell::Make (leadKey)};
5362
+ queueScan->LeadKey = leadKey_;
5363
+ env.SendAsync (std::move (queueScan));
5364
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5365
+ if (!expectedRowsCount) {
5366
+ break ;
5367
+ }
5368
+ }
5369
+
5370
+ // If we didn't crash, then assume the test succeeded
5371
+ env.SendSync (new TEvents::TEvPoison, false , true );
5372
+ }
5373
+
5167
5374
}
5168
5375
5169
5376
Y_UNIT_TEST_SUITE (TFlatTableExecutorStickyPages) {
0 commit comments