Skip to content

Commit 1ccc850

Browse files
committed
KIKIMR-19521 BTreeIndex TPart
1 parent a361f5b commit 1ccc850

20 files changed

+686
-71
lines changed

ydb/core/tablet_flat/flat_page_btree_index.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,33 +93,33 @@ namespace NKikimr::NTable::NPage {
9393
}
9494

9595
bool IsNull(TPos pos) const {
96-
ui8 x = IsNullBitmap[pos >> 3];
96+
ui8 x = reinterpret_cast<const ui8*>(this)[pos >> 3];
9797
return (x >> (pos & 7)) & 1;
9898
}
9999

100100
void SetNull(TPos pos) {
101-
ui8& x = IsNullBitmap[pos >> 3];
101+
ui8& x = reinterpret_cast<ui8*>(this)[pos >> 3];
102102
x |= (1 << (pos & 7));
103103
}
104104

105-
// 1 = null
106-
ui8 IsNullBitmap[0];
105+
// 1 bit = null
106+
ui8 IsNullBitmap_;
107107
} Y_PACKED;
108108

109-
static_assert(sizeof(TKey) == 0, "Invalid TBtreeIndexNode TKey size");
109+
static_assert(sizeof(TKey) == 1, "Invalid TBtreeIndexNode TKey size");
110110

111111
struct TChild {
112112
TPageId PageId;
113113
TRowId Count;
114114
TRowId ErasedCount;
115-
ui64 Size;
115+
ui64 DataSize;
116116

117117
auto operator<=>(const TChild&) const = default;
118118

119119
TString ToString() const noexcept
120120
{
121121
// copy values to prevent 'reference binding to misaligned address' error
122-
return TStringBuilder() << "PageId: " << TPageId(PageId) << " Count: " << TRowId(Count) << " Size: " << ui64(Size);
122+
return TStringBuilder() << "PageId: " << TPageId(PageId) << " Count: " << TRowId(Count) << " Erased: " << TRowId(ErasedCount) << " DataSize: " << ui64(DataSize);
123123
}
124124
} Y_PACKED;
125125

@@ -129,7 +129,7 @@ namespace NKikimr::NTable::NPage {
129129

130130
public:
131131
TBtreeIndexNode(TSharedData raw)
132-
: Raw(std::move(raw))
132+
: Raw(std::move(raw))
133133
{
134134
const auto data = NPage::TLabelWrapper().Read(Raw, EPage::BTreeIndex);
135135
Y_ABORT_UNLESS(data == ECodec::Plain && data.Version == 0);
@@ -180,5 +180,13 @@ namespace NKikimr::NTable::NPage {
180180

181181
struct TBtreeIndexMeta : public TBtreeIndexNode::TChild {
182182
size_t LevelsCount;
183+
ui64 IndexSize;
184+
185+
auto operator<=>(const TBtreeIndexMeta&) const = default;
186+
187+
TString ToString() const noexcept
188+
{
189+
return TStringBuilder() << TBtreeIndexNode::TChild::ToString() << " LevelsCount: " << LevelsCount << " IndexSize: " << IndexSize;
190+
}
183191
};
184192
}

ydb/core/tablet_flat/flat_page_btree_index_writer.h

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ namespace NKikimr::NTable::NPage {
3939
Y_ABORT_UNLESS(!End);
4040
}
4141

42+
void Reset() {
43+
Keys.clear();
44+
KeysSize = 0;
45+
Children.clear();
46+
Ptr = 0;
47+
End = 0;
48+
}
49+
4250
TString SerializeKey(TCellsRef cells) {
4351
Y_ABORT_UNLESS(cells.size() <= GroupInfo.KeyTypes.size());
4452

@@ -115,6 +123,10 @@ namespace NKikimr::NTable::NPage {
115123
return Keys.size();
116124
}
117125

126+
TPgSize CalcKeySizeWithMeta(TCellsRef cells) const noexcept {
127+
return sizeof(TRecordsEntry) + CalcKeySize(cells) + sizeof(TChild);
128+
}
129+
118130
private:
119131
TPgSize CalcKeySize(TCellsRef cells) const noexcept
120132
{
@@ -256,15 +268,15 @@ namespace NKikimr::NTable::NPage {
256268
return result;
257269
}
258270

259-
size_t GetKeysSize() {
271+
size_t GetKeysSize() const {
260272
return KeysSize;
261273
}
262274

263-
size_t GetKeysCount() {
275+
size_t GetKeysCount() const {
264276
return Keys.size();
265277
}
266278

267-
size_t GetChildrenCount() {
279+
size_t GetChildrenCount() const {
268280
return Children.size();
269281
}
270282

@@ -288,6 +300,19 @@ namespace NKikimr::NTable::NPage {
288300
Y_ABORT_UNLESS(NodeKeysMax >= NodeKeysMin);
289301
}
290302

303+
TPgSize CalcSize(TCellsRef cells) const {
304+
return Writer.CalcKeySizeWithMeta(cells);
305+
}
306+
307+
// returns approximate value, doesn't include new child creation on Flush step
308+
ui64 EstimateBytesUsed() const {
309+
ui64 result = IndexSize; // written bytes
310+
for (const auto &lvl : Levels) {
311+
result += CalcPageSize(lvl);
312+
}
313+
return result;
314+
}
315+
291316
void AddKey(TCellsRef cells) {
292317
Levels[0].PushKey(Writer.SerializeKey(cells));
293318
}
@@ -296,7 +321,7 @@ namespace NKikimr::NTable::NPage {
296321
// aggregate in order to perform search by row id from any leaf node
297322
child.Count = (ChildrenCount += child.Count);
298323
child.ErasedCount = (ChildrenErasedCount += child.ErasedCount);
299-
child.Size = (ChildrenSize += child.Size);
324+
child.DataSize = (ChildrenSize += child.DataSize);
300325

301326
Levels[0].PushChild(child);
302327
}
@@ -305,7 +330,7 @@ namespace NKikimr::NTable::NPage {
305330
for (size_t levelIndex = 0; levelIndex < Levels.size(); levelIndex++) {
306331
if (last && !Levels[levelIndex].GetKeysCount()) {
307332
Y_ABORT_UNLESS(Levels[levelIndex].GetChildrenCount() == 1, "Should be root");
308-
return TBtreeIndexMeta{ Levels[levelIndex].PopChild(), levelIndex };
333+
return TBtreeIndexMeta{ Levels[levelIndex].PopChild(), levelIndex, IndexSize };
309334
}
310335

311336
if (!TryFlush(levelIndex, pager, last)) {
@@ -318,10 +343,17 @@ namespace NKikimr::NTable::NPage {
318343
return { };
319344
}
320345

346+
void Reset() {
347+
IndexSize = 0;
348+
Writer.Reset();
349+
Levels = { TLevel() };
350+
ChildrenCount = 0;
351+
ChildrenErasedCount = 0;
352+
ChildrenSize = 0;
353+
}
354+
321355
private:
322356
bool TryFlush(size_t levelIndex, IPageWriter &pager, bool last) {
323-
Y_ABORT_UNLESS(Levels[levelIndex].GetKeysCount(), "Shouldn't have empty levels");
324-
325357
if (!last && Levels[levelIndex].GetKeysCount() <= 2 * NodeKeysMax) {
326358
// Note: node should meet both NodeKeysMin and NodeSize restrictions for split
327359

@@ -361,13 +393,15 @@ namespace NKikimr::NTable::NPage {
361393
}
362394
auto lastChild = Levels[levelIndex].PopChild();
363395
Writer.AddChild(lastChild);
364-
365-
auto pageId = pager.Write(Writer.Finish(), EPage::BTreeIndex, 0);
396+
397+
auto page = Writer.Finish();
398+
IndexSize += page.size();
399+
auto pageId = pager.Write(std::move(page), EPage::BTreeIndex, 0);
366400

367401
if (levelIndex + 1 == Levels.size()) {
368402
Levels.emplace_back();
369403
}
370-
Levels[levelIndex + 1].PushChild(TChild{pageId, lastChild.Count, lastChild.ErasedCount, lastChild.Size});
404+
Levels[levelIndex + 1].PushChild(TChild{pageId, lastChild.Count, lastChild.ErasedCount, lastChild.DataSize});
371405
if (!last) {
372406
Levels[levelIndex + 1].PushKey(Levels[levelIndex].PopKey());
373407
}
@@ -383,11 +417,13 @@ namespace NKikimr::NTable::NPage {
383417
return true;
384418
}
385419

386-
size_t CalcPageSize(TLevel& level) {
420+
size_t CalcPageSize(const TLevel& level) const {
387421
return Writer.CalcPageSize(level.GetKeysSize(), level.GetKeysCount());
388422
}
389423

390424
private:
425+
ui64 IndexSize = 0;
426+
391427
TBtreeIndexNodeWriter Writer;
392428
TVector<TLevel> Levels; // from bottom to top
393429

ydb/core/tablet_flat/flat_page_conf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ namespace NPage {
6262
ui32 PageSize = 7 * 1024; /* Data page target size */
6363
ui32 PageRows = Max<ui32>(); /* Max rows per page, for UTs */
6464
ui32 IndexMin = 32 * 1024; /* Index initial buffer size */
65+
66+
ui32 BTreeIndexNodeTargetSize = 7 * 1024; /* 1 GB of (up to) 140B keys leads to 3-level B-Tree index */
67+
ui32 BTreeIndexNodeKeysMin = 6; /* 1 GB of 7KB keys leads to 6-level B-Tree index (node size - ~42KB) */
68+
ui32 BTreeIndexNodeKeysMax = Max<ui32>(); /* for UTs */
6569
};
6670

6771
struct TConf {
@@ -79,6 +83,7 @@ namespace NPage {
7983

8084
bool Final = true;
8185
bool CutIndexKeys = true;
86+
bool WriteBTreeIndex = false;
8287
ui32 MaxLargeBlob = 8 * 1024 * 1024 - 8; /* Maximum large blob size */
8388
ui32 LargeEdge = Max<ui32>(); /* External blob edge size */
8489
ui32 SmallEdge = Max<ui32>(); /* Outer blobs edge bytes limit */

0 commit comments

Comments
 (0)