Skip to content

Commit 5829e39

Browse files
committed
charge index on start
1 parent e26247c commit 5829e39

File tree

2 files changed

+56
-157
lines changed

2 files changed

+56
-157
lines changed

ydb/core/tablet_flat/flat_stat_part_group_btree_index.h

Lines changed: 55 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -22,48 +22,16 @@ class TStatsPartGroupBtreeIndexIterator : public IStatsPartGroupIterator {
2222
TRowId BeginRowId;
2323
TRowId EndRowId;
2424
TCellsIterable BeginKey;
25-
TCellsIterable EndKey;
26-
std::optional<TBtreeIndexNode> Node;
27-
std::optional<TRecIdx> Pos;
2825
ui64 DataSize;
2926

30-
TNodeState(TPageId pageId, TRowId beginRowId, TRowId endRowId, TCellsIterable beginKey, TCellsIterable endKey, ui64 dataSize)
27+
TNodeState(TPageId pageId, TRowId beginRowId, TRowId endRowId, TCellsIterable beginKey, ui64 dataSize)
3128
: PageId(pageId)
3229
, BeginRowId(beginRowId)
3330
, EndRowId(endRowId)
3431
, BeginKey(beginKey)
35-
, EndKey(endKey)
3632
, DataSize(dataSize)
3733
{
3834
}
39-
40-
bool IsLastPos() const noexcept {
41-
Y_ABORT_UNLESS(Node);
42-
Y_ABORT_UNLESS(Pos);
43-
return *Pos == Node->GetKeysCount();
44-
}
45-
46-
bool IsFirstPos() const noexcept {
47-
Y_ABORT_UNLESS(Node);
48-
Y_ABORT_UNLESS(Pos);
49-
return *Pos == 0;
50-
}
51-
};
52-
53-
struct TSeekRowId {
54-
TSeekRowId(TRowId rowId)
55-
: RowId(rowId)
56-
{}
57-
58-
bool BelongsTo(const TNodeState& state) const noexcept {
59-
return TBtreeIndexNode::Has(RowId, state.BeginRowId, state.EndRowId);
60-
}
61-
62-
TRecIdx Do(const TNodeState& state) const noexcept {
63-
return state.Node->Seek(RowId, state.Pos);
64-
}
65-
66-
const TRowId RowId;
6735
};
6836

6937
public:
@@ -73,172 +41,103 @@ class TStatsPartGroupBtreeIndexIterator : public IStatsPartGroupIterator {
7341
, GroupId(groupId)
7442
, GroupInfo(part->Scheme->GetLayout(groupId))
7543
, Meta(groupId.IsHistoric() ? part->IndexPages.BTreeHistoric[groupId.Index] : part->IndexPages.BTreeGroups[groupId.Index])
76-
, State(Reserve(Meta.LevelCount + 1))
7744
, GroupChannel(Part->GetGroupChannel(GroupId))
45+
, NodeIndex(0)
7846
, PrevDataSize(0)
7947
, PrevPrevDataSize(0)
8048
{
81-
const static TCellsIterable EmptyKey(static_cast<const char*>(nullptr), TColumns());
82-
State.emplace_back(Meta.PageId, 0, GetEndRowId(), EmptyKey, EmptyKey, Meta.DataSize);
8349
}
8450

8551
EReady Start() override {
86-
return DoSeek<TSeekRowId>({0});
87-
}
88-
89-
EReady Next() override {
90-
Y_ABORT_UNLESS(!IsExhausted());
52+
const static TCellsIterable EmptyKey(static_cast<const char*>(nullptr), TColumns());
9153

92-
PrevPrevDataSize = PrevDataSize;
93-
PrevDataSize = State.back().DataSize;
54+
bool ready = true;
55+
TVector<TNodeState> nextNodes;
56+
Nodes.emplace_back(Meta.PageId, 0, GetEndRowId(), EmptyKey, Meta.DataSize);
57+
58+
for (ui32 height = 0; height < Meta.LevelCount; height++) {
59+
for (auto &nodeState : Nodes) {
60+
auto page = Env->TryGetPage(Part, nodeState.PageId);
61+
if (!page) {
62+
ready = false;
63+
continue;
64+
}
65+
TBtreeIndexNode node(*page);
66+
67+
for (TRecIdx pos : xrange<TRecIdx>(0, node.GetChildrenCount())) {
68+
auto& child = node.GetShortChild(pos);
69+
70+
TRowId beginRowId = pos ? node.GetShortChild(pos - 1).RowCount : nodeState.BeginRowId;
71+
TRowId endRowId = child.RowCount;
72+
TCellsIterable beginKey = pos ? node.GetKeyCellsIterable(pos - 1, GroupInfo.ColsKeyIdx) : nodeState.BeginKey;
73+
ui64 dataSize = child.DataSize;
74+
75+
nextNodes.emplace_back(child.PageId, beginRowId, endRowId, beginKey, dataSize);
76+
}
77+
}
9478

95-
if (Meta.LevelCount == 0) {
96-
return Exhaust();
79+
Nodes.swap(nextNodes);
80+
nextNodes.clear();
9781
}
9882

99-
if (IsLeaf()) {
100-
do {
101-
State.pop_back();
102-
} while (State.size() > 1 && State.back().IsLastPos());
103-
if (State.back().IsLastPos()) {
104-
return Exhaust();
105-
}
106-
PushNextState(*State.back().Pos + 1);
83+
if (!ready) {
84+
Nodes.clear(); // some invalid subset
85+
return EReady::Page;
10786
}
10887

109-
for (ui32 level : xrange<ui32>(State.size() - 1, Meta.LevelCount)) {
110-
if (!TryLoad(State[level])) {
111-
// exiting with an intermediate state
112-
Y_DEBUG_ABORT_UNLESS(!IsLeaf() && !IsExhausted());
113-
return EReady::Page;
114-
}
115-
PushNextState(0);
116-
}
88+
return DataOrGone();
89+
}
90+
91+
EReady Next() override {
92+
Y_ABORT_UNLESS(IsValid());
93+
94+
PrevPrevDataSize = PrevDataSize;
95+
PrevDataSize = GetCurrentNode().DataSize;
11796

118-
// State.back() points to the target data page
119-
Y_ABORT_UNLESS(IsLeaf());
120-
return EReady::Data;
97+
NodeIndex++;
98+
99+
return DataOrGone();
121100
}
122101

123102
void AddLastDeltaDataSize(TChanneledDataSize& dataSize) override {
124-
Y_ABORT_UNLESS(IsExhausted() || IsLeaf());
125103
Y_DEBUG_ABORT_UNLESS(PrevDataSize >= PrevPrevDataSize);
126104
ui64 delta = PrevDataSize - PrevPrevDataSize;
127105
dataSize.Add(delta, GroupChannel);
128106
}
129107

130108
public:
131109
bool IsValid() const override {
132-
Y_DEBUG_ABORT_UNLESS(IsLeaf() || IsExhausted());
133-
return IsLeaf();
110+
return NodeIndex < Nodes.size();
134111
}
135112

136113
TRowId GetEndRowId() const override {
137114
return Meta.RowCount;
138115
}
139116

140117
TPageId GetPageId() const override {
141-
Y_ABORT_UNLESS(IsLeaf());
142-
return State.back().PageId;
118+
return GetCurrentNode().PageId;
143119
}
144120

145121
TRowId GetRowId() const override {
146-
Y_ABORT_UNLESS(IsLeaf());
147-
return State.back().BeginRowId;
122+
return GetCurrentNode().BeginRowId;
148123
}
149124

150125
TPos GetKeyCellsCount() const override {
151-
Y_ABORT_UNLESS(IsLeaf());
152-
return State.back().BeginKey.Count();
126+
return GetCurrentNode().BeginKey.Count();
153127
}
154128

155129
TCell GetKeyCell(TPos index) const override {
156-
Y_ABORT_UNLESS(IsLeaf());
157-
return State.back().BeginKey.Iter().At(index);
130+
return GetCurrentNode().BeginKey.Iter().At(index);
158131
}
159132

160133
private:
161-
template<typename TSeek>
162-
EReady DoSeek(TSeek seek) {
163-
while (State.size() > 1 && !seek.BelongsTo(State.back())) {
164-
State.pop_back();
165-
}
166-
167-
if (IsExhausted()) {
168-
// don't use exhausted state as an initial one
169-
State[0].Pos = { };
170-
}
171-
172-
for (ui32 level : xrange<ui32>(State.size() - 1, Meta.LevelCount)) {
173-
auto &state = State[level];
174-
Y_DEBUG_ABORT_UNLESS(seek.BelongsTo(state));
175-
if (!TryLoad(state)) {
176-
// exiting with an intermediate state
177-
Y_DEBUG_ABORT_UNLESS(!IsLeaf() && !IsExhausted());
178-
return EReady::Page;
179-
}
180-
auto pos = seek.Do(state);
181-
182-
PushNextState(pos);
183-
}
184-
185-
// State.back() points to the target data page
186-
Y_ABORT_UNLESS(IsLeaf());
187-
Y_DEBUG_ABORT_UNLESS(seek.BelongsTo(State.back()));
188-
return EReady::Data;
189-
}
190-
191-
bool IsRoot() const noexcept {
192-
return State.size() == 1;
193-
}
194-
195-
bool IsExhausted() const noexcept {
196-
return State[0].Pos == Max<TRecIdx>();
134+
EReady DataOrGone() const {
135+
return IsValid() ? EReady::Data : EReady::Gone;
197136
}
198137

199-
bool IsLeaf() const noexcept {
200-
// Note: it is possible to have 0 levels in B-Tree
201-
// so we may have exhausted state with leaf (data) node
202-
return State.size() == Meta.LevelCount + 1 && !IsExhausted();
203-
}
204-
205-
EReady Exhaust() {
206-
while (State.size() > 1) {
207-
State.pop_back();
208-
}
209-
State[0].Pos = Max<TRecIdx>();
210-
return EReady::Gone;
211-
}
212-
213-
void PushNextState(TRecIdx pos) {
214-
TNodeState& current = State.back();
215-
Y_ABORT_UNLESS(pos < current.Node->GetChildrenCount(), "Should point to some child");
216-
current.Pos.emplace(pos);
217-
218-
auto& child = current.Node->GetShortChild(pos);
219-
220-
TRowId beginRowId = pos ? current.Node->GetShortChild(pos - 1).RowCount : current.BeginRowId;
221-
TRowId endRowId = child.RowCount;
222-
223-
TCellsIterable beginKey = pos ? current.Node->GetKeyCellsIterable(pos - 1, GroupInfo.ColsKeyIdx) : current.BeginKey;
224-
TCellsIterable endKey = pos < current.Node->GetKeysCount() ? current.Node->GetKeyCellsIterable(pos, GroupInfo.ColsKeyIdx) : current.EndKey;
225-
226-
ui64 dataSize = child.DataSize;
227-
228-
State.emplace_back(child.PageId, beginRowId, endRowId, beginKey, endKey, dataSize);
229-
}
230-
231-
bool TryLoad(TNodeState& state) {
232-
if (state.Node) {
233-
return true;
234-
}
235-
236-
auto page = Env->TryGetPage(Part, state.PageId);
237-
if (page) {
238-
state.Node.emplace(*page);
239-
return true;
240-
}
241-
return false;
138+
const TNodeState& GetCurrentNode() const {
139+
Y_ABORT_UNLESS(IsValid());
140+
return Nodes[NodeIndex];
242141
}
243142

244143
private:
@@ -247,8 +146,9 @@ class TStatsPartGroupBtreeIndexIterator : public IStatsPartGroupIterator {
247146
const TGroupId GroupId;
248147
const TPartScheme::TGroupInfo& GroupInfo;
249148
const TBtreeIndexMeta Meta;
250-
TVector<TNodeState> State;
251149
ui8 GroupChannel;
150+
ui32 NodeIndex;
151+
TVector<TNodeState> Nodes;
252152
ui64 PrevDataSize, PrevPrevDataSize;
253153
};
254154

ydb/core/tablet_flat/ut/ut_stat.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ namespace {
1414
const TSharedData* TryGetPage(const TPart *part, TPageId id, TGroupId groupId) override
1515
{
1616
UNIT_ASSERT_C(part->GetPageType(id) == EPage::Index || part->GetPageType(id) == EPage::BTreeIndex, "Shouldn't request non-index pages");
17-
// TODO: charge b-tree index
18-
if (!Touched[groupId].insert(id).second || part->GetPageType(id) == EPage::BTreeIndex) {
17+
if (!Touched[groupId].insert(id).second) {
1918
return NTest::TTestEnv::TryGetPage(part, id, groupId);
2019
}
2120
return nullptr;

0 commit comments

Comments
 (0)