Skip to content

v0.8.44: more search improvements - #7961

Merged
waleedlatif1 merged 6 commits into
mainfrom
staging
Sep 18, 2026
Merged

waleedlatif1 merged 6 commits into
mainfrom
staging

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

* chore(db): drop unused ANN indexes on embedding

Approximate retrieval is served by the compact embedding_search projection.
The only vector ordering left on embedding is an exact rerank wrapped as
(distance) + 0, which the planner cannot match to an index expression, and
the binary_quantize expression indexes were never referenced by any query.
The last app version that ordered by a bare distance has drained, so these
ten indexes were maintained on every chunk write while never being scanned.

* fix(knowledge): let the scale benchmark own its ANN index

The bulk-seed path required embedding_vector_hnsw_idx to exist, dropped it
before seeding and rebuilt it after. With no ANN index left in the schema it
threw before measuring anything. The benchmark seeds embedding directly and
never populates embedding_search, so it now creates its own HNSW index after
the load rather than borrowing a schema one, for both seed paths.
… page (#7956)

* fix(file-search): seek the backfill cursor instead of rescanning each page

The hourly backfill walks every live workspace file by `(workspace_id, id)`,
but no index supplied that order under its predicate, so each page sorted the
whole remaining set and the dispatcher's 10s statement timeout aborted the
transaction before any page committed.

Adds the matching partial index and compares the cursor row-wise. The previous
`workspace_id > :ws OR (workspace_id = :ws AND id > :id)` spelling is only ever
an index filter, never an index condition, so even with the index each page
restarted at the low end and rescanned every page before it.

On a prod-shaped fixture (5.5M files, 94k live) a full 95-page walk goes from
786ms to 42ms; the index alone accounts for 786ms -> 267ms and the row-wise
cursor for the rest.

* refactor(file-search): sharpen the backfill walk test and its docs

Bound the walk loop by the expected page count so a cursor regression fails on
the first extra page instead of looping; keep the fixture size off a page
multiple explicitly; drop a distinct-count assertion the primary key already
guarantees. Separate the two coupled causes in the TSDoc so neither reads as a
consequence of the other.

* fix(file-search): assert the backfill walk still plans as an index seek

Addresses both cubic findings.

Mark the index `.concurrently()` so a schema reconciliation outside the
hand-written migration also builds it without blocking writes, matching how
workflow_execution_logs_workspace_activity_idx is declared. Drizzle now emits
CREATE INDEX CONCURRENTLY itself; the migration keeps its hand-written wrapper
for lock_timeout and replay recovery.

The walk test only proved logical pagination, which the OR spelling also
satisfies. Record the statements the dispatcher issues and EXPLAIN the exact
backfill SELECT, requiring the cursor to appear as a row-wise index condition.
Reverting to the OR spelling now fails on the plan itself, not just on the SQL
text.

That assertion also exposed a third divergence in the fixture: workspace_id was
declared NOT NULL where production has it nullable, which let PostgreSQL drop
the walk's IS NOT NULL clause and then refuse to match the partial index at all.
…nd its probes (#7957)

* improvement(knowledge): instrument the search source overview and bound its probes

The source overview backs the Sim Search indexing banner and source filter, but
it emitted no telemetry, so a slow request could only be observed as a duration
on the route. It now shares the search diagnostics trace, timing availability
resolution, the provider read, and each per-batch indexing and searchable probe,
and records how many access batches and live source proofs a request consumed.

The access batch generator is instrumented in the same trace, separating the
connector discovery query from the live source proof that reaches the provider
over the network, so a slow batch says which half was slow for every caller.

The searchable probe also stops repeating: one searchable document is the whole
answer, yet the bounded existence query ran again for every remaining batch.

* fix(knowledge): report the free first access predicate separately

The batch counter started at one to include the ordinary predicate, which is
yielded without a connector query or a live source proof, while the field
documented every batch as costing both. The count now says what it measures,
and it is recorded before the first yield so a caller that stops consuming
there still reports the predicate it used.
* fix(knowledge): keep vector candidate selection bounded

An underfilled ANN traversal rescored the whole compact projection and joined the
visible document set to it. That fallback is O(corpus): on a 132k-chunk index it
took 1.9s, and on a corpus an order of magnitude larger it exceeds the retrieval
budget, so the vector leg returned nothing at all rather than fewer rows.

Widening the search has no affordable form here. Measured at 10% visibility on the
same index, scanning 6.5k tuples instead of 1.5k took 5.1s and 9.7s on consecutive
identical runs, and joining visibility before scoring took 8.4s because it turns a
sequential scan into a random lookup per document. The bounded traversal itself
costs ~115ms whether or not it fills.

The traversal is now the whole candidate set. An underfilled one yields fewer
candidates and is reported as such, which strictly beats a leg that times out.

* fix(knowledge): match the latency plan assertions to the bounded traversal

The plan assertion still required the removed CTEs, and the predicates selecting
which captured query to assert against matched the old CTE name with a lowercase
fallback the rendered statement never produces. The candidate assertions would
have stopped running rather than failing, so they now key on the visibility
lateral through one shared predicate.

The plan check drops the fallback-specific expectations and gains the one that
guards this change: the traversal must never reach the projection by document
lookup or sequential scan, at any candidate count.
@vercel

vercel Bot commented Sep 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Sep 18, 2026 5:26am UTC

Request Review

@waleedlatif1
waleedlatif1 merged commit 27ef3c9 into main Sep 18, 2026
63 checks passed
@greptile-apps

greptile-apps Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no actionable correctness, security, migration, or repository-rule issue remains.

Summary

This PR improves search responsiveness, observability, and failure diagnostics while updating the database indexes that support the revised query paths.

  • Docks organization search immediately after submission and delays filters until useful results are available.
  • Bounds vector candidate selection instead of falling back to corpus-wide rescoring.
  • Adds source-overview and access-batch search diagnostics.
  • Preserves safe Google and PostgreSQL failure details in connector and dispatcher logs.
  • Converts workspace-file backfill pagination to an indexed row-wise keyset seek.
  • Drops obsolete ANN indexes from the primary embedding table.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Search submission] --> B[Docked search layout]
  B --> C[Source overview]
  B --> D[Knowledge retrieval]
  C --> E[Access batches and bounded probes]
  D --> F[Keyword retrieval]
  D --> G[Bounded ANN traversal]
  G --> H[Exact rerank of selected candidates]
  F --> I[Result fusion]
  H --> I
  I --> J[Reveal filters and results]
  K[Workspace-file reconciliation] --> L[Row-wise keyset seek]
  L --> M[Revision jobs]
  N[Connector or database failure] --> O[Safe structured diagnostics]
Loading

Reviews (1) · Last reviewed commit: "fix(knowledge): keep vector candidate se..."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant