@@ -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
@@ -5020,7 +5033,14 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorIndexLoading) {
5020
5033
}
5021
5034
};
5022
5035
5023
- Y_UNIT_TEST (TestPrechargeAndSeek_FlatIndex) {
5036
+ void ZeroSharedCache (TMyEnvBase &env) {
5037
+ env.Env .GetMemObserver ()->NotifyStat ({1 , 1 , 1 });
5038
+ TDispatchOptions options;
5039
+ options.FinalEvents .push_back (TDispatchOptions::TFinalEventCondition (NSharedCache::EvMem, 1 ));
5040
+ env->DispatchEvents (options);
5041
+ }
5042
+
5043
+ Y_UNIT_TEST (PrechargeAndSeek_FlatIndex) {
5024
5044
TMyEnvBase env;
5025
5045
TRowsModel rows;
5026
5046
@@ -5065,7 +5085,7 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorIndexLoading) {
5065
5085
env.SendSync (new TEvents::TEvPoison, false , true );
5066
5086
}
5067
5087
5068
- Y_UNIT_TEST (TestPrechargeAndSeek_BTreeIndex ) {
5088
+ Y_UNIT_TEST (PrechargeAndSeek_BTreeIndex ) {
5069
5089
TMyEnvBase env;
5070
5090
TRowsModel rows;
5071
5091
@@ -5110,6 +5130,193 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorIndexLoading) {
5110
5130
env.SendSync (new TEvents::TEvPoison, false , true );
5111
5131
}
5112
5132
5133
+ Y_UNIT_TEST (Scan_BTreeIndex) {
5134
+ TMyEnvBase env;
5135
+ TRowsModel rows;
5136
+ const ui32 rowsCount = 1024 ;
5137
+
5138
+ auto &appData = env->GetAppData ();
5139
+ appData.FeatureFlags .SetEnableLocalDBBtreeIndex (true );
5140
+ appData.FeatureFlags .SetEnableLocalDBFlatIndex (false );
5141
+
5142
+ env->SetLogPriority (NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_DEBUG);
5143
+
5144
+ env.FireTablet (env.Edge , env.Tablet , [&env](const TActorId &tablet, TTabletStorageInfo *info) {
5145
+ return new TTestFlatTablet (env.Edge , tablet, info);
5146
+ });
5147
+ env.WaitForWakeUp ();
5148
+ ZeroSharedCache (env);
5149
+
5150
+ env.SendSync (rows.MakeScheme (new TCompactionPolicy (), false ));
5151
+
5152
+ env.SendSync (rows.MakeRows (rowsCount, 10 *1024 ));
5153
+
5154
+ env.SendSync (new NFake::TEvCompact (TRowsModel::TableId));
5155
+ env.WaitFor <NFake::TEvCompacted>();
5156
+
5157
+ { // no read ahead
5158
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5159
+ queueScan->ReadAhead = {1 , 1 };
5160
+ env.SendAsync (std::move (queueScan));
5161
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5162
+ }
5163
+
5164
+ { // small read ahead
5165
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5166
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5167
+ env.SendAsync (std::move (queueScan));
5168
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5169
+ }
5170
+
5171
+ { // infinite read ahead
5172
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5173
+ queueScan->ReadAhead = {Max<ui64>(), Max<ui64>()};
5174
+ env.SendAsync (std::move (queueScan));
5175
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5176
+ }
5177
+
5178
+ for (ui64 leadKey = 1 ; ; leadKey += rowsCount / 10 ) {
5179
+ ui64 expectedRowsCount = rowsCount > leadKey ? rowsCount - leadKey + 1 : 0 ;
5180
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (expectedRowsCount);
5181
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5182
+ TVector<TCell> leadKey_ = {TCell::Make (leadKey)};
5183
+ queueScan->LeadKey = leadKey_;
5184
+ env.SendAsync (std::move (queueScan));
5185
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5186
+ if (!expectedRowsCount) {
5187
+ break ;
5188
+ }
5189
+ }
5190
+
5191
+ // If we didn't crash, then assume the test succeeded
5192
+ env.SendSync (new TEvents::TEvPoison, false , true );
5193
+ }
5194
+
5195
+ Y_UNIT_TEST (Scan_History_BTreeIndex) {
5196
+ TMyEnvBase env;
5197
+ TRowsModel rows;
5198
+ const ui32 rowsCount = 1024 ;
5199
+
5200
+ auto &appData = env->GetAppData ();
5201
+ appData.FeatureFlags .SetEnableLocalDBBtreeIndex (true );
5202
+ appData.FeatureFlags .SetEnableLocalDBFlatIndex (false );
5203
+
5204
+ env->SetLogPriority (NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_DEBUG);
5205
+
5206
+ env.FireTablet (env.Edge , env.Tablet , [&env](const TActorId &tablet, TTabletStorageInfo *info) {
5207
+ return new TTestFlatTablet (env.Edge , tablet, info);
5208
+ });
5209
+ env.WaitForWakeUp ();
5210
+ ZeroSharedCache (env);
5211
+
5212
+ env.SendSync (rows.MakeScheme (new TCompactionPolicy (), false ));
5213
+
5214
+ env.SendSync (rows.RowTo (1 ).VersionTo (TRowVersion (1 , 10 )).MakeRows (rowsCount, 10 *1024 ));
5215
+ env.SendSync (rows.RowTo (1 ).VersionTo (TRowVersion (2 , 20 )).MakeRows (rowsCount, 10 *1024 ));
5216
+
5217
+ env.SendSync (new NFake::TEvCompact (TRowsModel::TableId));
5218
+ env.WaitFor <NFake::TEvCompacted>();
5219
+
5220
+ { // no read ahead
5221
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount, TRowVersion (2 , 0 ));
5222
+ queueScan->ReadAhead = {1 , 1 };
5223
+ env.SendAsync (std::move (queueScan));
5224
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5225
+ }
5226
+
5227
+ { // small read ahead
5228
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount, TRowVersion (2 , 0 ));
5229
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5230
+ env.SendAsync (std::move (queueScan));
5231
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5232
+ }
5233
+
5234
+ { // infinite read ahead
5235
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount, TRowVersion (2 , 0 ));
5236
+ queueScan->ReadAhead = {Max<ui64>(), Max<ui64>()};
5237
+ env.SendAsync (std::move (queueScan));
5238
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5239
+ }
5240
+
5241
+ for (ui64 leadKey = 1 ; ; leadKey += rowsCount / 10 ) {
5242
+ ui64 expectedRowsCount = rowsCount > leadKey ? rowsCount - leadKey + 1 : 0 ;
5243
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (expectedRowsCount, TRowVersion (2 , 0 ));
5244
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5245
+ TVector<TCell> leadKey_ = {TCell::Make (leadKey)};
5246
+ queueScan->LeadKey = leadKey_;
5247
+ env.SendAsync (std::move (queueScan));
5248
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5249
+ if (!expectedRowsCount) {
5250
+ break ;
5251
+ }
5252
+ }
5253
+
5254
+ // If we didn't crash, then assume the test succeeded
5255
+ env.SendSync (new TEvents::TEvPoison, false , true );
5256
+ }
5257
+
5258
+ Y_UNIT_TEST (Scan_Groups_BTreeIndex) {
5259
+ TMyEnvBase env;
5260
+ TRowsModel rows;
5261
+ const ui32 rowsCount = 1024 ;
5262
+
5263
+ auto &appData = env->GetAppData ();
5264
+ appData.FeatureFlags .SetEnableLocalDBBtreeIndex (true );
5265
+ appData.FeatureFlags .SetEnableLocalDBFlatIndex (false );
5266
+
5267
+ env->SetLogPriority (NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_DEBUG);
5268
+
5269
+ env.FireTablet (env.Edge , env.Tablet , [&env](const TActorId &tablet, TTabletStorageInfo *info) {
5270
+ return new TTestFlatTablet (env.Edge , tablet, info);
5271
+ });
5272
+ env.WaitForWakeUp ();
5273
+ ZeroSharedCache (env);
5274
+
5275
+ env.SendSync (rows.MakeScheme (new TCompactionPolicy (), true ));
5276
+
5277
+ env.SendSync (rows.MakeRows (rowsCount, 10 *1024 ));
5278
+
5279
+ env.SendSync (new NFake::TEvCompact (TRowsModel::TableId));
5280
+ env.WaitFor <NFake::TEvCompacted>();
5281
+
5282
+ { // no read ahead
5283
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5284
+ queueScan->ReadAhead = {1 , 1 };
5285
+ env.SendAsync (std::move (queueScan));
5286
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5287
+ }
5288
+
5289
+ { // small read ahead
5290
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5291
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5292
+ env.SendAsync (std::move (queueScan));
5293
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5294
+ }
5295
+
5296
+ { // infinite read ahead
5297
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (rowsCount);
5298
+ queueScan->ReadAhead = {Max<ui64>(), Max<ui64>()};
5299
+ env.SendAsync (std::move (queueScan));
5300
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5301
+ }
5302
+
5303
+ for (ui64 leadKey = 1 ; ; leadKey += rowsCount / 10 ) {
5304
+ ui64 expectedRowsCount = rowsCount > leadKey ? rowsCount - leadKey + 1 : 0 ;
5305
+ auto queueScan = new TEvTestFlatTablet::TEvQueueScan (expectedRowsCount);
5306
+ queueScan->ReadAhead = {5 *10 *1024 , 10 *10 *1024 };
5307
+ TVector<TCell> leadKey_ = {TCell::Make (leadKey)};
5308
+ queueScan->LeadKey = leadKey_;
5309
+ env.SendAsync (std::move (queueScan));
5310
+ env.WaitFor <TEvTestFlatTablet::TEvScanFinished>();
5311
+ if (!expectedRowsCount) {
5312
+ break ;
5313
+ }
5314
+ }
5315
+
5316
+ // If we didn't crash, then assume the test succeeded
5317
+ env.SendSync (new TEvents::TEvPoison, false , true );
5318
+ }
5319
+
5113
5320
}
5114
5321
5115
5322
Y_UNIT_TEST_SUITE (TFlatTableExecutorStickyPages) {
0 commit comments