@@ -13,22 +13,27 @@ class TChargeBTreeIndex : public ICharge {
13
13
using TGroupId = NPage::TGroupId;
14
14
using TChild = TBtreeIndexNode::TChild;
15
15
16
- // TODO: store PageId only instead of TChild?
17
- struct TChildState : TChild {
16
+ // TODO: store PageId only?
17
+ struct TChildState {
18
+ TPageId PageId;
18
19
TRowId BeginRowId;
19
20
TRowId EndRowId;
21
+ TRowId RowCount;
22
+ ui64 DataSize;
20
23
21
- TChildState (TChild meta , TRowId beginRowId, TRowId endRowId)
22
- : TChild(meta )
24
+ TChildState (TPageId pageId , TRowId beginRowId, TRowId endRowId, TRowId rowCount, ui64 dataSize )
25
+ : PageId(pageId )
23
26
, BeginRowId(beginRowId)
24
27
, EndRowId(endRowId)
28
+ , RowCount(rowCount)
29
+ , DataSize(dataSize)
25
30
{
26
31
}
27
32
};
28
33
29
34
struct TNodeState : TChildState, TBtreeIndexNode {
30
- TNodeState (TSharedData data, TChild meta , TRowId beginRowId, TRowId endRowId)
31
- : TChildState(meta , beginRowId, endRowId)
35
+ TNodeState (TSharedData data, TPageId pageId , TRowId beginRowId, TRowId endRowId, TRowId rowCount, ui64 dataSize )
36
+ : TChildState(pageId , beginRowId, endRowId, rowCount, dataSize )
32
37
, TBtreeIndexNode(data)
33
38
{
34
39
}
@@ -62,15 +67,15 @@ class TChargeBTreeIndex : public ICharge {
62
67
63
68
public:
64
69
TResult Do (TCells key1, TCells key2, TRowId beginRowId, TRowId endRowId,
65
- const TKeyCellDefaults &keyDefaults, ui64 itemsLimit , ui64 bytesLimit ) const noexcept override {
70
+ const TKeyCellDefaults &keyDefaults, ui64 rowCountLimit , ui64 dataSizeLimit ) const noexcept override {
66
71
endRowId++; // current interface accepts inclusive row2 bound
67
72
Y_ABORT_UNLESS (beginRowId < endRowId);
68
73
69
- bool ready = true ;
74
+ bool ready = true , overshot = true ;
70
75
bool chargeGroups = bool (Groups); // false value means that beginRowId, endRowId are invalid and shouldn't be used
76
+ ui64 rowCount = 0 , dataSize = 0 ;
71
77
72
- Y_UNUSED (itemsLimit);
73
- Y_UNUSED (bytesLimit);
78
+ Y_UNUSED (rowCountLimit, dataSizeLimit, rowCount, dataSize);
74
79
75
80
const auto & meta = Part->IndexPages .BTreeGroups [0 ];
76
81
Y_ABORT_UNLESS (endRowId <= meta.RowCount );
@@ -103,16 +108,32 @@ class TChargeBTreeIndex : public ICharge {
103
108
}
104
109
for (TRecIdx pos : xrange (from, to)) {
105
110
auto child = node.GetChild (pos);
106
- TRowId beginRowId = pos ? node.GetChild (pos - 1 ).RowCount : node.BeginRowId ;
107
- TRowId endRowId = child.RowCount ;
108
- ready &= tryHandleChild (TChildState (child, beginRowId, endRowId));
111
+ if (pos) {
112
+ auto prev = node.GetChild (pos - 1 );
113
+ ready &= tryHandleChild (TChildState (child.PageId , prev.RowCount , child.RowCount ,
114
+ child.GetNonErasedRowCount () - prev.GetNonErasedRowCount (),
115
+ child.DataSize - prev.DataSize ));
116
+ } else {
117
+ ready &= tryHandleChild (TChildState (child.PageId , 0 , child.RowCount ,
118
+ child.GetNonErasedRowCount (),
119
+ child.DataSize ));
120
+ }
109
121
}
110
122
}
111
123
};
112
124
125
+ const auto skipUnloadedRows = [&](const TChildState& child) {
126
+ if (child.PageId == key1PageId) {
127
+ beginRowId = Max (beginRowId, child.EndRowId );
128
+ }
129
+ if (child.PageId == key2PageId) {
130
+ endRowId = Min (endRowId, child.BeginRowId );
131
+ }
132
+ };
133
+
113
134
const auto tryHandleNode = [&](TChildState child) -> bool {
114
135
if (child.PageId == key1PageId || child.PageId == key2PageId) {
115
- if (TryLoadNode (child, nextLevel)) { // update beginRowId, endRowId
136
+ if (TryLoadNode (child, nextLevel)) {
116
137
const auto & node = nextLevel.back ();
117
138
if (child.PageId == key1PageId) {
118
139
TRecIdx pos = node.Seek (ESeek::Lower, key1, Scheme.Groups [0 ].ColsKeyIdx , &keyDefaults);
@@ -130,13 +151,8 @@ class TChargeBTreeIndex : public ICharge {
130
151
}
131
152
}
132
153
return true ;
133
- } else { // skip unloaded page rows
134
- if (child.PageId == key1PageId) {
135
- beginRowId = Max (beginRowId, child.EndRowId );
136
- }
137
- if (child.PageId == key2PageId) {
138
- endRowId = Min (endRowId, child.BeginRowId );
139
- }
154
+ } else {
155
+ skipUnloadedRows (child);
140
156
return false ;
141
157
}
142
158
} else {
@@ -147,7 +163,7 @@ class TChargeBTreeIndex : public ICharge {
147
163
const auto tryHandleDataPage = [&](TChildState child) -> bool {
148
164
if (chargeGroups && (child.PageId == key1PageId || child.PageId == key2PageId)) {
149
165
const auto page = TryGetDataPage (child.PageId , { });
150
- if (page) { // update beginRowId, endRowId
166
+ if (page) {
151
167
auto data = NPage::TDataPage (page);
152
168
if (child.PageId == key1PageId) {
153
169
TRowId key1RowId = data.BaseRow () + data.LookupKey (key1, Scheme.Groups [0 ], ESeek::Lower, &keyDefaults).Off ();
@@ -158,13 +174,8 @@ class TChargeBTreeIndex : public ICharge {
158
174
endRowId = Min (endRowId, key2RowId);
159
175
}
160
176
return true ;
161
- } else { // skip unloaded page rows
162
- if (child.PageId == key1PageId) {
163
- beginRowId = Max (beginRowId, child.EndRowId );
164
- }
165
- if (child.PageId == key2PageId) {
166
- endRowId = Min (endRowId, child.BeginRowId );
167
- }
177
+ } else {
178
+ skipUnloadedRows (child);
168
179
return false ;
169
180
}
170
181
} else {
@@ -174,7 +185,7 @@ class TChargeBTreeIndex : public ICharge {
174
185
175
186
for (ui32 height = 0 ; height < meta.LevelCount && ready; height++) {
176
187
if (height == 0 ) {
177
- ready &= tryHandleNode (TChildState (meta, 0 , meta.RowCount ));
188
+ ready &= tryHandleNode (TChildState (meta. PageId , 0 , meta.RowCount , meta. GetNonErasedRowCount (), meta. DataSize ));
178
189
} else {
179
190
iterateLevel (tryHandleNode);
180
191
}
@@ -189,10 +200,10 @@ class TChargeBTreeIndex : public ICharge {
189
200
190
201
// flat index doesn't treat key placement within data page, so let's do the same
191
202
// TODO: remove it later
192
- bool overshot = endRowId == sliceEndRowId;
203
+ overshot & = endRowId == sliceEndRowId;
193
204
194
205
if (meta.LevelCount == 0 ) {
195
- ready &= tryHandleDataPage (TChildState (meta, 0 , meta.RowCount ));
206
+ ready &= tryHandleDataPage (TChildState (meta. PageId , 0 , meta.RowCount , meta. GetNonErasedRowCount (), meta. DataSize ));
196
207
} else {
197
208
iterateLevel (tryHandleDataPage);
198
209
}
@@ -203,15 +214,15 @@ class TChargeBTreeIndex : public ICharge {
203
214
}
204
215
205
216
TResult DoReverse (TCells key1, TCells key2, TRowId endRowId, TRowId beginRowId,
206
- const TKeyCellDefaults &keyDefaults, ui64 itemsLimit , ui64 bytesLimit ) const noexcept override {
217
+ const TKeyCellDefaults &keyDefaults, ui64 rowCountLimit , ui64 dataSizeLimit ) const noexcept override {
207
218
endRowId++; // current interface accepts inclusive row1 bound
208
219
Y_ABORT_UNLESS (beginRowId < endRowId);
209
220
210
- bool ready = true ;
221
+ bool ready = true , overshot = true ;
211
222
bool chargeGroups = bool (Groups); // false value means that beginRowId, endRowId are invalid and shouldn't be used
223
+ ui64 rowCount = 0 , dataSize = 0 ;
212
224
213
- Y_UNUSED (itemsLimit);
214
- Y_UNUSED (bytesLimit);
225
+ Y_UNUSED (rowCountLimit, dataSizeLimit, rowCount, dataSize);
215
226
216
227
const auto & meta = Part->IndexPages .BTreeGroups [0 ];
217
228
Y_ABORT_UNLESS (endRowId <= meta.RowCount );
@@ -244,16 +255,32 @@ class TChargeBTreeIndex : public ICharge {
244
255
}
245
256
for (TRecIdx pos : xrange (from, to)) {
246
257
auto child = node.GetChild (pos);
247
- TRowId beginRowId = pos ? node.GetChild (pos - 1 ).RowCount : node.BeginRowId ;
248
- TRowId endRowId = child.RowCount ;
249
- ready &= tryHandleChild (TChildState (child, beginRowId, endRowId));
258
+ if (pos) {
259
+ auto prev = node.GetChild (pos - 1 );
260
+ ready &= tryHandleChild (TChildState (child.PageId , prev.RowCount , child.RowCount ,
261
+ child.GetNonErasedRowCount () - prev.GetNonErasedRowCount (),
262
+ child.DataSize - prev.DataSize ));
263
+ } else {
264
+ ready &= tryHandleChild (TChildState (child.PageId , 0 , child.RowCount ,
265
+ child.GetNonErasedRowCount (),
266
+ child.DataSize ));
267
+ }
250
268
}
251
269
}
252
270
};
253
271
272
+ const auto skipUnloadedRows = [&](TChildState child) {
273
+ if (child.PageId == key1PageId) {
274
+ endRowId = Min (endRowId, child.BeginRowId );
275
+ }
276
+ if (child.PageId == key2PageId) {
277
+ beginRowId = Max (beginRowId, child.EndRowId );
278
+ }
279
+ };
280
+
254
281
const auto tryHandleNode = [&](TChildState child) -> bool {
255
282
if (child.PageId == key1PageId || child.PageId == key2PageId) {
256
- if (TryLoadNode (child, nextLevel)) { // update beginRowId, endRowId
283
+ if (TryLoadNode (child, nextLevel)) {
257
284
const auto & node = nextLevel.back ();
258
285
if (child.PageId == key1PageId) {
259
286
TRecIdx pos = node.SeekReverse (ESeek::Lower, key1, Scheme.Groups [0 ].ColsKeyIdx , &keyDefaults);
@@ -271,13 +298,8 @@ class TChargeBTreeIndex : public ICharge {
271
298
}
272
299
}
273
300
return true ;
274
- } else { // skip unloaded page rows
275
- if (child.PageId == key1PageId) {
276
- endRowId = Min (endRowId, child.BeginRowId );
277
- }
278
- if (child.PageId == key2PageId) {
279
- beginRowId = Max (beginRowId, child.EndRowId );
280
- }
301
+ } else {
302
+ skipUnloadedRows (child);
281
303
return false ;
282
304
}
283
305
} else {
@@ -288,7 +310,7 @@ class TChargeBTreeIndex : public ICharge {
288
310
const auto tryHandleDataPage = [&](TChildState child) -> bool {
289
311
if (chargeGroups && (child.PageId == key1PageId || child.PageId == key2PageId)) {
290
312
const auto page = TryGetDataPage (child.PageId , { });
291
- if (page) { // update beginRowId, endRowId
313
+ if (page) {
292
314
auto data = NPage::TDataPage (page);
293
315
if (child.PageId == key1PageId) {
294
316
auto iter = data.LookupKeyReverse (key1, Scheme.Groups [0 ], ESeek::Lower, &keyDefaults);
@@ -309,13 +331,8 @@ class TChargeBTreeIndex : public ICharge {
309
331
}
310
332
}
311
333
return true ;
312
- } else { // skip unloaded page rows
313
- if (child.PageId == key1PageId) {
314
- endRowId = Min (endRowId, child.BeginRowId );
315
- }
316
- if (child.PageId == key2PageId) {
317
- beginRowId = Max (beginRowId, child.EndRowId );
318
- }
334
+ } else {
335
+ skipUnloadedRows (child);
319
336
return false ;
320
337
}
321
338
} else {
@@ -325,7 +342,7 @@ class TChargeBTreeIndex : public ICharge {
325
342
326
343
for (ui32 height = 0 ; height < meta.LevelCount && ready; height++) {
327
344
if (height == 0 ) {
328
- ready &= tryHandleNode (TChildState (meta, 0 , meta.RowCount ));
345
+ ready &= tryHandleNode (TChildState (meta. PageId , 0 , meta.RowCount , meta. GetNonErasedRowCount (), meta. DataSize ));
329
346
} else {
330
347
iterateLevel (tryHandleNode);
331
348
}
@@ -340,10 +357,10 @@ class TChargeBTreeIndex : public ICharge {
340
357
341
358
// flat index doesn't treat key placement within data page, so let's do the same
342
359
// TODO: remove it later
343
- bool overshot = beginRowId == sliceBeginRowId;
360
+ overshot & = beginRowId == sliceBeginRowId;
344
361
345
362
if (meta.LevelCount == 0 ) {
346
- ready &= tryHandleDataPage (TChildState (meta, 0 , meta.RowCount ));
363
+ ready &= tryHandleDataPage (TChildState (meta. PageId , 0 , meta.RowCount , meta. GetNonErasedRowCount (), meta. DataSize ));
347
364
} else {
348
365
iterateLevel (tryHandleDataPage);
349
366
}
@@ -384,9 +401,16 @@ class TChargeBTreeIndex : public ICharge {
384
401
}
385
402
for (TRecIdx pos : xrange (from, to)) {
386
403
auto child = node.GetChild (pos);
387
- TRowId beginRowId = pos ? node.GetChild (pos - 1 ).RowCount : node.BeginRowId ;
388
- TRowId endRowId = child.RowCount ;
389
- ready &= tryHandleChild (TChildState (child, beginRowId, endRowId));
404
+ if (pos) {
405
+ auto prev = node.GetChild (pos - 1 );
406
+ ready &= tryHandleChild (TChildState (child.PageId , prev.RowCount , child.RowCount ,
407
+ child.GetNonErasedRowCount () - prev.GetNonErasedRowCount (),
408
+ child.DataSize - prev.DataSize ));
409
+ } else {
410
+ ready &= tryHandleChild (TChildState (child.PageId , 0 , child.RowCount ,
411
+ child.GetNonErasedRowCount (),
412
+ child.DataSize ));
413
+ }
390
414
}
391
415
}
392
416
};
@@ -401,7 +425,7 @@ class TChargeBTreeIndex : public ICharge {
401
425
402
426
for (ui32 height = 0 ; height < meta.LevelCount && ready; height++) {
403
427
if (height == 0 ) {
404
- ready &= tryHandleNode (TChildState (meta, 0 , meta.RowCount ));
428
+ ready &= tryHandleNode (TChildState (meta. PageId , 0 , meta.RowCount , meta. RowCount , meta. DataSize ));
405
429
} else {
406
430
iterateLevel (tryHandleNode);
407
431
}
@@ -414,7 +438,7 @@ class TChargeBTreeIndex : public ICharge {
414
438
}
415
439
416
440
if (meta.LevelCount == 0 ) {
417
- ready &= tryHandleDataPage (TChildState (meta, 0 , meta.RowCount ));
441
+ ready &= tryHandleDataPage (TChildState (meta. PageId , 0 , meta.RowCount , meta. RowCount , meta. DataSize ));
418
442
} else {
419
443
iterateLevel (tryHandleDataPage);
420
444
}
@@ -441,7 +465,7 @@ class TChargeBTreeIndex : public ICharge {
441
465
return true ;
442
466
}
443
467
444
- int Compare (TCells left, TCells right, const TKeyCellDefaults & keyDefaults) const noexcept
468
+ int Compare (TCells left, TCells right, const TKeyCellDefaults& keyDefaults) const noexcept
445
469
{
446
470
Y_DEBUG_ABORT_UNLESS (left, " Empty keys should be handled separately" );
447
471
Y_DEBUG_ABORT_UNLESS (right, " Empty keys should be handled separately" );
0 commit comments