-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[fix](be) Keep a requested constant value on a column reader cache hit #68018
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,6 +60,15 @@ std::shared_ptr<ColumnReader> ColumnReaderCache::_lookup(const ColumnReaderCache | |
|
|
||
| void ColumnReaderCache::_insert_locked_nocheck(const ColumnReaderCacheKey& key, | ||
| const std::shared_ptr<ColumnReader>& reader) { | ||
| // Replacing an existing key updates its node in place. Pushing a second node for the same key | ||
| // would leave the first one unreachable in the list while eviction erases the map entry of | ||
| // whichever copy reaches the tail, dropping the live reader from the map. | ||
| if (auto it = _cache_map.find(key); it != _cache_map.end()) { | ||
| it->second->reader = reader; | ||
| it->second->last_access = std::chrono::steady_clock::now(); | ||
| _lru_list.splice(_lru_list.begin(), _lru_list, it->second); | ||
| return; | ||
| } | ||
| // If capacity exceeded, remove least recently used (tail) | ||
| if (_cache_map.size() >= config::max_segment_partial_column_cache_size) { | ||
| g_segment_column_reader_cache_count << -1; | ||
|
|
@@ -98,8 +107,12 @@ Status ColumnReaderCache::get_column_reader(int32_t col_uid, | |
| OlapReaderStatistics* stats, | ||
| const io::IOContext* source_io_ctx, | ||
| std::optional<Field> const_value) { | ||
| // Attempt to find in cache | ||
| if (auto cached = _lookup({col_uid, {}})) { | ||
| // A caller that passes const_value reads a column whose on-disk value is a placeholder, so it | ||
| // must not be served the on-disk reader that a caller without const_value cached earlier: that | ||
| // reader would hand back the placeholder both as row data and as a zone map. Fall through and | ||
| // build the constant reader, replacing the cached entry so later callers get the real value too. | ||
| if (auto cached = _lookup({col_uid, {}}); | ||
| cached != nullptr && (!const_value.has_value() || cached->is_constant())) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Keep constant readers out of physical index initialization. With an inverted index on |
||
| *column_reader = cached; | ||
| return Status::OK(); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] Preserve the constant reader across concurrent misses.
_lookupreleases_cache_mutexbefore construction, so a bare request can miss and start building the physical reader, a constant request can then insert and return its reader, and the first request reaches this branch last and overwrites it. Since a cachedSegmentis shared, a query that already created aConstantColumnIteratorcan then do the bare index lookup and receive the placeholder's physical index; for example, real commit TSO 42 withtso > 20can be eliminated by an index containing 0, with the predicate removed from row fallback. This is the inverse concurrent order from the existing sequential comment. Please make the compare-and-upsert constant-dominant regardless of arrival order, return the selected authoritative reader to the caller, and add a barrier-controlled mixed physical/constant miss test.