Skip to content

Commit 0588587

Browse files
[Enhancement] Make the segment iterator reusable across scans
Add the segment-layer machinery for reusing a SegmentIterator across multiple scans instead of building a fresh one each time, plus the prepared-scan-range plumbing that a reused iterator consumes: - SegmentIterator::reset_for_reuse() / _init_reused_scan() and a one-time-setup split (ScanContext::reset, _init_scan_range_and_context, _one_time_setup_done) so per-scan state is reset while the expensive one-time setup is preserved; - Segment::new_reusable_iterator() + new_reusable_segment_iterator(); - NonClosingChunkIterator so a finishing driver does not tear down the shared reused iterator; - SegmentReadStateCache on SegmentReadOptions and _apply_precomputed_scan_range() so a reused iterator can skip re-pruning when a precomputed scan range is supplied, plus the _get_prepared_pruned_row_ranges() helper that computes it; - BitmapIndexEvaluator::init() idempotency reset so it can be re-initialized on reuse. Infrastructure only: nothing populates the read-state cache or calls reset_for_reuse yet (the lake prepared physical split scan follow-ups do). No behavior change on the existing scan path. Signed-off-by: stephen <stephen5217@163.com>
1 parent 6583314 commit 0588587

11 files changed

Lines changed: 627 additions & 56 deletions

be/src/storage/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ set(STORAGE_FILES
4646
segment_flush_executor.cpp
4747
segment_replicate_executor.cpp
4848
metadata_util.cpp
49+
non_closing_chunk_iterator.cpp
4950
kv_store.cpp
5051
local_tablet_reader.cpp
5152
olap_server.cpp
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2021-present StarRocks, Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "storage/non_closing_chunk_iterator.h"
16+
17+
#include <memory>
18+
#include <unordered_set>
19+
#include <utility>
20+
#include <vector>
21+
22+
namespace starrocks {
23+
24+
class NonClosingChunkIterator final : public ChunkIterator {
25+
public:
26+
explicit NonClosingChunkIterator(ChunkIteratorPtr child)
27+
: ChunkIterator(child->schema(), child->chunk_size()), _child(std::move(child)) {}
28+
29+
void close() override {}
30+
31+
size_t merged_rows() const override { return _child->merged_rows(); }
32+
33+
Status init_encoded_schema(ColumnIdToGlobalDictMap& dict_maps) override {
34+
RETURN_IF_ERROR(ChunkIterator::init_encoded_schema(dict_maps));
35+
return _child->init_encoded_schema(dict_maps);
36+
}
37+
38+
Status init_output_schema(const std::unordered_set<uint32_t>& unused_output_column_ids) override {
39+
RETURN_IF_ERROR(ChunkIterator::init_output_schema(unused_output_column_ids));
40+
return _child->init_output_schema(unused_output_column_ids);
41+
}
42+
43+
protected:
44+
Status do_get_next(Chunk* chunk) override { return _child->get_next(chunk); }
45+
Status do_get_next(Chunk* chunk, std::vector<uint32_t>* rowid) override { return _child->get_next(chunk, rowid); }
46+
Status do_get_next(Chunk* chunk, std::vector<uint64_t>* rssid_rowids) override {
47+
return _child->get_next(chunk, rssid_rowids);
48+
}
49+
50+
private:
51+
ChunkIteratorPtr _child;
52+
};
53+
54+
ChunkIteratorPtr new_non_closing_chunk_iterator(const ChunkIteratorPtr& child) {
55+
return std::make_shared<NonClosingChunkIterator>(child);
56+
}
57+
58+
} // namespace starrocks
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2021-present StarRocks, Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include "storage_primitive/chunk_iterator.h"
18+
19+
namespace starrocks {
20+
21+
// Wraps |child| as a per-scan iterator without taking ownership of its close
22+
// lifecycle. The slot owner must close |child| explicitly.
23+
ChunkIteratorPtr new_non_closing_chunk_iterator(const ChunkIteratorPtr& child);
24+
25+
} // namespace starrocks

be/src/storage/rowset/bitmap_index_evaluator.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ void BitmapIndexEvaluator::close() {
414414
}
415415

416416
Status BitmapIndexEvaluator::init(BitmapIndexIteratorSupplier&& supplier) {
417+
close();
418+
_closed = false;
419+
_ctx = BitmapContext{};
420+
_has_bitmap_index = false;
421+
_bitmap_index_iterators.clear();
417422
_bitmap_index_iterators.resize(ChunkSchemaHelper::max_column_id(_schema) + 1, nullptr);
418423
ASSIGN_OR_RETURN(_has_bitmap_index,
419424
_pred_tree.visit(BitmapIndexInitializer{this, supplier}, nullptr, CompoundNodeType::AND));

be/src/storage/rowset/segment.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,7 @@ struct SegmentZoneMapPruner {
338338
const SegmentReadOptions& read_options;
339339
};
340340

341-
StatusOr<ChunkIteratorPtr> Segment::_new_iterator(const Schema& schema, const SegmentReadOptions& read_options) {
342-
DCHECK(read_options.stats != nullptr);
343-
341+
Status Segment::_prune_by_segment_zone_map(const SegmentReadOptions& read_options) {
344342
const auto pruned = config::enable_index_segment_level_zonemap_filter &&
345343
read_options.pred_tree_for_zone_map.visit(SegmentZoneMapPruner{this, read_options});
346344
if (pruned) {
@@ -349,7 +347,13 @@ StatusOr<ChunkIteratorPtr> Segment::_new_iterator(const Schema& schema, const Se
349347
}
350348
return Status::EndOfFile(strings::Substitute("End of file $0, empty iterator", _segment_file_info.path));
351349
}
350+
return Status::OK();
351+
}
352352

353+
StatusOr<ChunkIteratorPtr> Segment::_new_iterator(const Schema& schema, const SegmentReadOptions& read_options) {
354+
DCHECK(read_options.stats != nullptr);
355+
356+
RETURN_IF_ERROR(_prune_by_segment_zone_map(read_options));
353357
return new_segment_iterator(shared_from_this(), schema, read_options);
354358
}
355359

@@ -360,6 +364,17 @@ StatusOr<ChunkIteratorPtr> Segment::new_iterator(const Schema& schema, const Seg
360364
return _new_iterator(schema, read_options);
361365
}
362366

367+
StatusOr<ChunkIteratorPtr> Segment::new_reusable_iterator(const Schema& iterator_schema, const Schema& output_schema,
368+
const SegmentReadOptions& read_options,
369+
ChunkIteratorPtr* reusable_slot) {
370+
if (read_options.stats == nullptr) {
371+
return Status::InvalidArgument("stats is null pointer");
372+
}
373+
RETURN_IF_ERROR(_prune_by_segment_zone_map(read_options));
374+
return new_reusable_segment_iterator(shared_from_this(), iterator_schema, output_schema, read_options,
375+
reusable_slot);
376+
}
377+
363378
Status Segment::new_inverted_index_iterator(uint32_t ucid, InvertedIndexIterator** iter, const SegmentReadOptions& opts,
364379
const IndexReadOptions& index_opt) {
365380
auto column_reader_iter = _column_readers.find(ucid);

be/src/storage/rowset/segment.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class Segment : public std::enable_shared_from_this<Segment> {
108108

109109
// may return EndOfFile
110110
StatusOr<ChunkIteratorPtr> new_iterator(const Schema& schema, const SegmentReadOptions& read_options);
111+
StatusOr<ChunkIteratorPtr> new_reusable_iterator(const Schema& iterator_schema, const Schema& output_schema,
112+
const SegmentReadOptions& read_options,
113+
ChunkIteratorPtr* reusable_slot);
111114

112115
StatusOr<std::shared_ptr<Segment>> new_dcg_segment(const DeltaColumnGroup& dcg, uint32_t idx,
113116
const TabletSchemaCSPtr& read_tablet_schema);
@@ -302,6 +305,7 @@ class Segment : public std::enable_shared_from_this<Segment> {
302305
std::unordered_map<uint32_t, uint32_t>& column_id_to_footer_ordinal);
303306

304307
StatusOr<ChunkIteratorPtr> _new_iterator(const Schema& schema, const SegmentReadOptions& read_options);
308+
Status _prune_by_segment_zone_map(const SegmentReadOptions& read_options);
305309

306310
bool _use_segment_zone_map_filter(const SegmentReadOptions& read_options);
307311

0 commit comments

Comments
 (0)