Skip to content

Commit 2aeaca6

Browse files
authored
feat(btree): refactor GlobalIndexScan & add inte test for btree global index (alibaba#262)
1 parent 6695b84 commit 2aeaca6

153 files changed

Lines changed: 3193 additions & 1442 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

include/paimon/defs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ struct PAIMON_EXPORT Options {
365365
static const char BLOB_AS_DESCRIPTOR[];
366366
/// "global-index.enabled" - Whether to enable global index for scan. Default value is "true".
367367
static const char GLOBAL_INDEX_ENABLED[];
368+
/// "global-index.thread-num" - The maximum number of concurrent scanner for global index. No
369+
/// default value. By default is the number of processors available to the machine.
370+
static const char GLOBAL_INDEX_THREAD_NUM[];
368371
/// "global-index.external-path" - Global index root directory, if not set, the global index
369372
/// files will be stored under the index directory.
370373
static const char GLOBAL_INDEX_EXTERNAL_PATH[];

include/paimon/global_index/global_index_reader.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ namespace paimon {
3131
///
3232
/// Derived classes are expected to implement the visitor methods (e.g., `VisitEqual`,
3333
/// `VisitIsNull`, etc.) to return index-based results that indicate which
34-
/// row satisfy the given predicate.
35-
///
36-
/// @note All `GlobalIndexResult` objects returned by implementations of this class use **local row
37-
/// ids** that start from 0 — not global row ids in the entire table.
38-
/// The `GlobalIndexResult` can be converted to global row ids by calling `AddOffset()`.
34+
/// rows satisfy the given predicate.
3935
class PAIMON_EXPORT GlobalIndexReader : public FunctionVisitor<std::shared_ptr<GlobalIndexResult>> {
4036
public:
4137
/// VisitVectorSearch performs approximate vector similarity search.

include/paimon/global_index/global_index_result.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@
2727
#include "paimon/visibility.h"
2828

2929
namespace paimon {
30-
/// Global index result to get selected global row ids.
30+
/// Global index result that holds the row ids.
3131
class PAIMON_EXPORT GlobalIndexResult : public std::enable_shared_from_this<GlobalIndexResult> {
3232
public:
3333
virtual ~GlobalIndexResult() = default;
3434

35-
/// Iterator interface for traversing selected global row ids.
35+
/// Iterator interface for traversing selected row ids.
3636
class Iterator {
3737
public:
3838
virtual ~Iterator() = default;
3939

4040
/// Checks whether more row ids are available.
4141
virtual bool HasNext() const = 0;
4242

43-
/// @return The next global row id and advances the iterator.
43+
/// @return The next row id and advances the iterator.
4444
virtual int64_t Next() = 0;
4545
};
4646

@@ -53,7 +53,7 @@ class PAIMON_EXPORT GlobalIndexResult : public std::enable_shared_from_this<Glob
5353
/// (e.g., during lazy loading of index data).
5454
virtual Result<bool> IsEmpty() const = 0;
5555

56-
/// Creates a new iterator over the selected global row ids.
56+
/// Creates a new iterator over the selected row ids.
5757
virtual Result<std::unique_ptr<Iterator>> CreateIterator() const = 0;
5858

5959
/// Returns non-overlapping, sorted ranges covering all row ids in `GlobalIndexResult`.
@@ -125,7 +125,7 @@ class PAIMON_EXPORT ScoredGlobalIndexResult : public GlobalIndexResult {
125125
/// Retrieves the next (row_id, score) pair and advances the iterator.
126126
///
127127
/// @return A pair where:
128-
/// - first: the global row id (returned in ascending order),
128+
/// - first: the row id (returned in ascending order).
129129
/// - second: the associated score computed by the index.
130130
///
131131
/// @note The sequence is ordered by **row_id**, not by score.

include/paimon/global_index/global_index_scan.h

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,70 +23,92 @@
2323
#include <string>
2424
#include <vector>
2525

26-
#include "paimon/global_index/row_range_global_index_scanner.h"
26+
#include "paimon/global_index/global_index_reader.h"
27+
#include "paimon/global_index/global_index_result.h"
28+
#include "paimon/predicate/predicate.h"
2729
#include "paimon/utils/range.h"
30+
#include "paimon/utils/row_range_index.h"
2831
#include "paimon/visibility.h"
29-
3032
namespace paimon {
3133
class MemoryPool;
3234
class FileSystem;
35+
3336
/// Represents a logical scan over a global index for a table.
3437
class PAIMON_EXPORT GlobalIndexScan {
3538
public:
3639
/// Creates a `GlobalIndexScan` instance for the specified table and context.
37-
///
3840
/// @param table_path Root directory of the table.
3941
/// @param snapshot_id Optional snapshot id to read from; if not provided, uses the latest.
4042
/// @param partitions Optional list of specific partitions to restrict the scan scope.
4143
/// Each map represents one partition (e.g., {"dt": "2024-06-01"}).
42-
/// If omitted, scans all partitions.
43-
/// @param options Index-specific configuration.
44+
/// If omitted (`std::nullopt`), scans all partitions of the table.
45+
/// @param options User defined configuration.
4446
/// @param file_system File system for accessing index files.
4547
/// If not provided (nullptr), it is inferred from the `FILE_SYSTEM`
4648
/// key in the `options` parameter.
49+
/// @param executor The executor to be used for asynchronous operations during global
50+
/// index scan.
4751
/// @param pool Memory pool for temporary allocations; if nullptr, uses default.
4852
/// @return A `Result` containing a unique pointer to the created scanner,
49-
/// or an error if initialization fails (e.g., I/O error).
53+
/// or an error if initialization fails (e.g., I/O error, invalid snapshot id,
54+
/// unknown partition).
5055
static Result<std::unique_ptr<GlobalIndexScan>> Create(
5156
const std::string& table_path, const std::optional<int64_t>& snapshot_id,
5257
const std::optional<std::vector<std::map<std::string, std::string>>>& partitions,
5358
const std::map<std::string, std::string>& options,
54-
const std::shared_ptr<FileSystem>& file_system, const std::shared_ptr<MemoryPool>& pool);
59+
const std::shared_ptr<FileSystem>& file_system, const std::shared_ptr<Executor>& executor,
60+
const std::shared_ptr<MemoryPool>& pool);
5561

56-
/// Creates a `GlobalIndexScan` instance for the specified table and context.
57-
///
58-
/// @param partition_filters Optional specific partition predicates.
62+
/// Creates a `GlobalIndexScan` instance for the specified table and context, with a
63+
/// predicate-based partition filter.
64+
/// @param root_path Root directory of the table.
65+
/// @param snapshot_id Optional snapshot id to read from; if not provided, uses the
66+
/// latest snapshot.
67+
/// @param partition_filters Optional partition-level predicate used for partition pruning.
68+
/// If nullptr, all partitions are scanned.
69+
/// @param options User defined configuration.
70+
/// @param file_system File system for accessing index files. If nullptr, it is
71+
/// inferred from the `FILE_SYSTEM` key in `options`.
72+
/// @param executor The executor to be used for asynchronous operations during global
73+
/// index scan.
74+
/// @param pool Memory pool for temporary allocations; if nullptr, uses default.
75+
/// @return A `Result` containing a unique pointer to the created scanner,
76+
/// or an error if initialization fails.
5977
static Result<std::unique_ptr<GlobalIndexScan>> Create(
6078
const std::string& root_path, const std::optional<int64_t>& snapshot_id,
6179
const std::shared_ptr<Predicate>& partition_filters,
6280
const std::map<std::string, std::string>& options,
63-
const std::shared_ptr<FileSystem>& file_system,
64-
const std::shared_ptr<MemoryPool>& memory_pool);
81+
const std::shared_ptr<FileSystem>& file_system, const std::shared_ptr<Executor>& executor,
82+
const std::shared_ptr<MemoryPool>& pool);
6583

6684
virtual ~GlobalIndexScan() = default;
6785

68-
/// Creates a scanner for the global index over the specified row id range.
69-
///
70-
/// This method instantiates a low-level scanner that can evaluate predicates and
71-
/// retrieve matching row ids from the global index data corresponding to the given
72-
/// row id range.
73-
///
74-
/// @param range The inclusive row id range [start, end] for which to create the scanner.
75-
/// The range must be fully covered by existing global index data (from
76-
/// `GetRowRangeList()`).
77-
/// @return A `Result` containing a range-level scanner, or an error if parse index meta fails.
78-
virtual Result<std::shared_ptr<RowRangeGlobalIndexScanner>> CreateRangeScan(
79-
const Range& range) = 0;
86+
/// Creates several `GlobalIndexReader`s for a specific field.
87+
/// @param field_name Name of the indexed column.
88+
/// @param row_range_index Optional row range that limits the scan to a sub-range of row ids.
89+
/// If not provided, the entire row range is considered.
90+
/// @return A `Result` that is:
91+
/// - Successful with several readers(with global row id) if the indexes exist and load
92+
/// correctly;
93+
/// - Successful with an empty vector if no index was built for the given field;
94+
/// - Error returns when loading fails (e.g., file corruption, I/O error,
95+
/// unsupported format).
96+
virtual Result<std::vector<std::shared_ptr<GlobalIndexReader>>> CreateReaders(
97+
const std::string& field_name,
98+
const std::optional<RowRangeIndex>& row_range_index) const = 0;
8099

81-
/// Returns row id ranges covered by this global index (sorted and non-overlapping
82-
/// ranges).
83-
///
84-
/// Each `Range` represents a contiguous segment of row ids for which global index
85-
/// data exists. This allows the query engine to parallelize scanning and be aware
86-
/// of ranges that are not covered by any global index.
87-
///
88-
/// @return A `Result` containing sorted and non-overlapping `Range` objects.
89-
virtual Result<std::vector<Range>> GetRowRangeList() = 0;
100+
/// Creates several `GlobalIndexReader`s for a specific field (looked up by id),
101+
/// @param field_id Field id of the indexed column.
102+
/// @param row_range_index Optional row range that limits the scan to a sub-range of row ids.
103+
/// If not provided, the entire row range is considered.
104+
/// @return A `Result` that is:
105+
/// - Successful with several readers(with global row id) if the indexes exist and load
106+
/// correctly;
107+
/// - Successful with an empty vector if no index was built for the given field;
108+
/// - Error returns when loading fails (e.g., file corruption, I/O error,
109+
/// unsupported format).
110+
virtual Result<std::vector<std::shared_ptr<GlobalIndexReader>>> CreateReaders(
111+
int32_t field_id, const std::optional<RowRangeIndex>& row_range_index) const = 0;
90112
};
91113

92114
} // namespace paimon

include/paimon/global_index/row_range_global_index_scanner.h

Lines changed: 0 additions & 60 deletions
This file was deleted.

include/paimon/scan_context.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
#include "paimon/global_index/global_index_result.h"
2727
#include "paimon/predicate/predicate.h"
28-
#include "paimon/predicate/vector_search.h"
2928
#include "paimon/result.h"
3029
#include "paimon/type_fwd.h"
3130
#include "paimon/visibility.h"
@@ -104,19 +103,14 @@ class PAIMON_EXPORT ScanFilter {
104103
public:
105104
ScanFilter(const std::shared_ptr<Predicate>& predicate,
106105
const std::vector<std::map<std::string, std::string>>& partition_filters,
107-
const std::optional<int32_t>& bucket_filter,
108-
const std::shared_ptr<VectorSearch>& vector_search)
106+
const std::optional<int32_t>& bucket_filter)
109107
: predicates_(predicate),
110-
vector_search_(vector_search),
111108
bucket_filter_(bucket_filter),
112109
partition_filters_(partition_filters) {}
113110

114111
std::shared_ptr<Predicate> GetPredicate() const {
115112
return predicates_;
116113
}
117-
std::shared_ptr<VectorSearch> GetVectorSearch() const {
118-
return vector_search_;
119-
}
120114
std::optional<int32_t> GetBucketFilter() const {
121115
return bucket_filter_;
122116
}
@@ -126,7 +120,6 @@ class PAIMON_EXPORT ScanFilter {
126120

127121
private:
128122
std::shared_ptr<Predicate> predicates_;
129-
std::shared_ptr<VectorSearch> vector_search_;
130123
std::optional<int32_t> bucket_filter_;
131124
std::vector<std::map<std::string, std::string>> partition_filters_;
132125
};
@@ -155,8 +148,6 @@ class PAIMON_EXPORT ScanContextBuilder {
155148
ScanContextBuilder& SetGlobalIndexResult(
156149
const std::shared_ptr<GlobalIndexResult>& global_index_result);
157150

158-
/// Set vector search for similarity search.
159-
ScanContextBuilder& SetVectorSearch(const std::shared_ptr<VectorSearch>& vector_search);
160151
/// The options added or set in `ScanContextBuilder` have high priority and will be merged with
161152
/// the options in table schema.
162153
ScanContextBuilder& AddOption(const std::string& key, const std::string& value);

src/paimon/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ set(PAIMON_COMMON_SRCS
5353
common/fs/resolving_file_system.cpp
5454
common/fs/file_system_factory.cpp
5555
common/global_config.cpp
56+
common/global_index/union_global_index_reader.cpp
57+
common/global_index/offset_global_index_reader.cpp
5658
common/global_index/complete_index_score_batch_reader.cpp
5759
common/global_index/bitmap_scored_global_index_result.cpp
5860
common/global_index/bitmap_global_index_result.cpp
@@ -195,7 +197,6 @@ set(PAIMON_CORE_SRCS
195197
core/global_index/global_index_evaluator_impl.cpp
196198
core/global_index/global_index_scan.cpp
197199
core/global_index/global_index_scan_impl.cpp
198-
core/global_index/row_range_global_index_scanner_impl.cpp
199200
core/global_index/global_index_write_task.cpp
200201
core/index/index_file_handler.cpp
201202
core/index/global_index_meta.cpp
@@ -413,6 +414,8 @@ if(PAIMON_BUILD_TESTS)
413414
common/global_index/complete_index_score_batch_reader_test.cpp
414415
common/global_index/global_index_result_test.cpp
415416
common/global_index/global_index_utils_test.cpp
417+
common/global_index/offset_global_index_reader_test.cpp
418+
common/global_index/union_global_index_reader_test.cpp
416419
common/global_index/global_indexer_factory_test.cpp
417420
common/global_index/bitmap_global_index_result_test.cpp
418421
common/global_index/bitmap_scored_global_index_result_test.cpp

src/paimon/common/defs.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const char Options::DATA_EVOLUTION_ENABLED[] = "data-evolution.enabled";
9191
const char Options::PARTITION_GENERATE_LEGACY_NAME[] = "partition.legacy-name";
9292
const char Options::BLOB_AS_DESCRIPTOR[] = "blob-as-descriptor";
9393
const char Options::GLOBAL_INDEX_ENABLED[] = "global-index.enabled";
94+
const char Options::GLOBAL_INDEX_THREAD_NUM[] = "global-index.thread-num";
9495
const char Options::GLOBAL_INDEX_EXTERNAL_PATH[] = "global-index.external-path";
9596
const char Options::AGGREGATION_REMOVE_RECORD_ON_DELETE[] = "aggregation.remove-record-on-delete";
9697
const char Options::SCAN_TIMESTAMP_MILLIS[] = "scan.timestamp-millis";

src/paimon/common/global_index/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ set(PAIMON_GLOBAL_INDEX_SRC
2525
btree/lazy_filtered_btree_reader.cpp
2626
btree/key_serializer.cpp
2727
rangebitmap/range_bitmap_global_index.cpp
28-
rangebitmap/range_bitmap_global_index_factory.cpp)
28+
rangebitmap/range_bitmap_global_index_factory.cpp
29+
offset_global_index_reader.cpp
30+
union_global_index_reader.cpp)
2931

3032
add_paimon_lib(paimon_global_index
3133
SOURCES

src/paimon/common/global_index/btree/btree_file_meta_selector_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ TEST_F(BTreeFileMetaSelectorTest, TestVisitIn) {
182182
// 1 in [1,10]=file1, [1,5]=file4
183183
// 2 in [1,10]=file1, [1,5]=file4
184184
// 3 in [1,10]=file1, [1,5]=file4
185-
// 26 in [21,30]=file3, [19,25]=file5
185+
// 26 in [21,30]=file3
186186
// 27 in [21,30]=file3
187187
// 28 in [21,30]=file3
188188
ASSERT_OK_AND_ASSIGN(auto result, selector.VisitIn({Literal(1), Literal(2), Literal(3),

0 commit comments

Comments
 (0)