Repository navigation
fix: don't scan the whole table to discover Map keys - #3082
Conversation
🦋 Changeset detectedLatest commit: 812939d The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@niladrix719 is attempting to deploy a commit to the HyperDX Team on Vercel. A member of the Team first needs to authorize it. |
|
Deep ReviewScope: PR #3082 — bound Map-key autocomplete discovery to a time window (#3037). 16 files, ~446 insertions across the merge-base range ✅ No critical issues found. The fix is sound for the wired call sites: the text-index paths now refuse to run without a 🟡 P2 — recommended
🔵 P3 nitpicks (2)
Reviewers (5): correctness, testing, typescript, performance, previous-comments. Testing gaps: New UI call-site wiring ( No finding blocks merge automatically. A maintainer will expect P0/P1 findings in code this PR changes to be fixed; P2/P3 are your call -- fix or reply. Never fix findings about surrounding code here; reply instead. Do not widen the PR. How to respond |
a3fb411 to
02b87c1
Compare
1712d3d to
bc6864f
Compare
bc6864f to
fc153e3
Compare
PR Review
5 finding(s): 🔴 0 critical · 🟠 1 major · 🔵 4 minor 4 posted as inline comment(s) on the changed lines. 1 listed below. Findings outside the changed lines
Severity is the reviewer's own estimate and is used for ordering, not filtering. No finding blocks merge automatically; a maintainer decides. |
fc153e3 to
1a29213
Compare
1a29213 to
001e0be
Compare
001e0be to
b3d622e
Compare
b3d622e to
518c53b
Compare
518c53b to
78143e9
Compare
78143e9 to
51a52da
Compare
51a52da to
91d76d3
Compare
a66b36a to
dbae808
Compare
| `Skipping Map key discovery for ${databaseName}.${tableName}.${column}: no timestampValueExpression to bound the scan`, | ||
| ); | ||
| // Cache so getAllFields doesn't re-warn per Map column on every call. | ||
| this.cache.set(cacheKey, []); |
There was a problem hiding this comment.
🟠 major — Skip branch caches [] under a key that omits timestampValueExpression on the metadataMVs path
When metadataMVs is set, cacheKey (lines 924-925) is built only from the aligned range and leaves out timestampValueExpression. The new skip branch then writes [] to that key. Suppose a log or trace source has MVs whose rollup is empty for Map columns, which the PR's own comment says is the norm. If an editor gets tcFromSource(source) without a sourceId and so calls first with no timestamp expression, every later call for the same column and range that does pass the expression hits the cached [] and never reaches the bounded scan. MetadataCache (line 206) has no TTL, so this lasts until the page reloads. Fix: add timestampValueExpression to the MV-path key, or return [] from the skip branch without writing it to the shared cacheKey. Add a test that calls without and then with the expression.
Nothing blocks merge automatically, but a maintainer will expect this fixed if it is a real defect in code this PR changes. If it is about surrounding code, reply and say so instead of patching. Do not widen the PR. How to respond
| inlineNonNegativeInt(maxKeys, 'maxKeys'); | ||
|
|
||
| // Default a missing range instead of scanning unbounded. #3037 | ||
| const dateRange = callerDateRange ?? defaultFieldMetadataDateRange(); |
There was a problem hiding this comment.
🔵 minor — Only the defaulted range is hour-aligned, so every caller-supplied range runs a fresh raw scan
defaultFieldMetadataDateRange is hour-aligned so the cache rotates hourly, but a callerDateRange goes into dateRangeCacheSuffix and timeFilterExpr unaligned on the non-MV path. This PR now passes the chart editor's dateRange into many editors, so every time-picker change or relative-range refresh gives a new cache key and a new main-table scan. Before, those editors hit one cached entry. Fix: align callerDateRange too, e.g. getAlignedDateRange(callerDateRange, '1 hour'), before building the key and filter.
Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond
| const FIELD_METADATA_LOOKBACK_MS = 24 * 60 * 60 * 1000; | ||
|
|
||
| // Hour-aligned so a range-keyed cache rotates hourly instead of every call. | ||
| export function defaultFieldMetadataDateRange(): [Date, Date] { |
There was a problem hiding this comment.
🔵 minor — defaultFieldMetadataDateRange is exported but has no callers outside this file
Grep shows the only use is getMapKeys at line 914 (the tests don't import it either). Drop the export, or use it in describeSource.ts in place of its hand-rolled VALUE_SAMPLE_LOOKBACK_MS range so there is one default.
Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond
| dateRange && timestampValueExpression | ||
| ? `${dateRange[0].getTime()}-${dateRange[1].getTime()}-${timestampValueExpression}` | ||
| : ''; | ||
| const dateRangeCacheSuffix = `${dateRange[0].getTime()}-${dateRange[1].getTime()}-${timestampValueExpression ?? ''}`; |
There was a problem hiding this comment.
🟠 major — Map key cache key now includes a date range the query ignores when there is no timestampValueExpression, so the full-table scan re-runs
When timestampValueExpression is missing, the scan has no time filter, so its result doesn't depend on dateRange. The cache key still includes it. Before this PR the suffix was '' in this case and the key never changed. Now the defaulted hour-aligned range gives a new key every hour, and a caller-supplied range gives a new key on every change. Each new key re-runs the full-table scan, and MetadataCache has no TTL or eviction, so entries also pile up. Fix: use a suffix without the range when timestampValueExpression is unset, e.g. timestampValueExpression ? ${dateRange[0].getTime()}-${dateRange[1].getTime()}-${timestampValueExpression} : '', and do the same for the alignedDateRange key.
Nothing blocks merge automatically, but a maintainer will expect this fixed if it is a real defect in code this PR changes. If it is about surrounding code, reply and say so instead of patching. Do not widen the PR. How to respond
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@knudtty Thanks for the review, I saw you made some additional improvements as well. Thanks for taking the time to do that |
Fixes #3037
Summary
getMapKeysonly added a time filter when the caller happened to pass both a date range and a timestamp expression. Several UI autocomplete call sites (chart editor, alert modal, dashboard filters) passed neither. When that happened, it fell back to an unbounded scan across the whole table instead of skipping or narrowing the querySteps to reproduce
open the chart editor, don't touch the time picker, and start typing a Group By expression on a Map column (
ResourceAttributes[). that keystroke sent ClickHouse a query with no time filter, reading every part of the table, not just recent onesThe fix
Both the raw-table scan and the text-index lookup now refuse to run without something to bound them. Field autocomplete falls back to a 24h window when it
knows the timestamp column but not the range, and the call sites that had a source/date range in scope but weren't passing them now do
Before / after
Before:
No
WHERE/predicate, full-table scanAfter:
Known gap
The SQL editors in source-configuration forms still don't pass scope, so Map keys won't autocomplete there. Left as a follow-up, needs the form's in-progress
timestampValueExpression, which isn't available the same way