v0.8.49: knowledge search improvements, tables perf improvements - #8108
Conversation
… search deadline, and drop the dead search paths (#8101)
…end on protocol (#8104) * improvement(tables): cut the DB round trips a table read and write spend on protocol The grid's first page spent more time on round trips than on work. Four of them were avoidable: - `pendingDeleteMask` probed `table_jobs` on every read, though the table a request just loaded already carries its latest non-export job, and the `one_active_per_table` unique index makes that row the running delete when one exists. Callers that hold a table across a long walk (the export stream, the snapshot builder) keep probing per page, so a delete starting mid-walk still begins masking. - The run-state sidecar was read for every table, including the ones that declare no workflow group and therefore cannot have a row — four chunked queries on a 1000-row page, all returning nothing. - The drain opened a transaction per batch. The guards are fixed for the call, so each extra batch paid `BEGIN` + `set_config` + `COMMIT` for nothing. - `setTableTxTimeouts` issued three `SET LOCAL` statements; `set_config(…, true)` is the same thing and fits in one round trip, as the read guards already do. A 1000-row page goes from 22 statements to 14, a 50-row page from 15 to 13, and every write transaction drops two. * review(tables): drop the delete-mask elision and correct the provenance snapshot doc Reading the delete job from the table a request already loaded widened a race the mask probe has always had — a job committing between the check and the row read is missed either way, but trusting the loaded fields moves the check two queries earlier. Closing it properly means evaluating the job inside the row read's own snapshot, which is a larger change than this one, so the elision is removed and `pending-delete-mask.ts` is back to what it was. The three remaining reductions are untouched: they were the bulk of the win, and each is a read this code cannot need rather than a read it takes on faith. Also updates `TableRowProvenanceReader`'s doc, which still described one repeatable-read transaction per batch.
…d binary ANN indexes (#8105)
…#8107) Two round trips a table request paid for data it was already carrying: - `checkAccess` — the gate every raw `/api/table/**` route shares — resolved the caller's workspace access, then asked the capability check for `tables.use` without telling it which organization owns the workspace. The resolver looks that up itself when it is omitted, so the workspace was read twice per request. It now goes through `checkWorkspaceAccess`, which `getUserEntityPermissions` already delegates to, and passes the organization it hands back. Same single resolution, one fewer read, on views, dispatches, export, import, columns, metadata and the rest. - An appending insert asked for `max(order_key)` and `max(position)` as two statements, both inside the row-order advisory lock every other inserting request is queued behind. Postgres plans each `max()` as its own InitPlan, so one statement still serves each from its own index — the same two index-only backward scans, in one round trip instead of two. Statements per request: views 7→6, dispatches 8→7, export 14→13, insert 14→13.
… exactly (#8106) * fix(knowledge): walk a large bounded set on the row before ranking it exactly A member reading most of a large source, with that source selected as a filter, enumerated a bounded permitted set of tens of thousands of documents and then ranked every chunk of it exactly on both legs: the vector leg read every chunk's projected vector, and the keyword leg materialized every chunk of the set before it matched the term. Cold, each leg outran its budget and the search returned nothing. A bounded set past a size limit is now walked on the row first, where the plan's source and ACL decide readability and the walk stops at its tuple cap, and ranked exactly only when the walk cannot fill its pool, so recall is never below the exact ranking's. The keyword leg treats the same set as a narrow on-row reader: Tin windows where Tin serves, otherwise the GIN shape whose cost follows the term's matches. Sets under the limit keep their exact paths. * fix(knowledge): refill a large bounded set's pool with the exact ranking once hydration runs it short The walk decides readability on the projection row, which is broader than the document predicate hydration applies, so a pool the walk filled can still run short of readable rows. The refill for a large bounded set is now the exact ranking, complete over the set, placed behind the rows already read so the pages keep their offsets. * fix(knowledge): rank a large bounded set's refill past the rows already read The refill's exact ranking excludes the chunks the pool already holds inside the statement, so every refill is a full window of fresh rows rather than a window thinned by the rows the walk found first. * fix(knowledge): hand a large bounded set's exhausted Tin windows to the GIN ranking A narrow reader's page is left short by design once the widest window cannot fill it; a large bounded set's read was exhaustive before, so its widest window that still falls short now hands the page to the GIN ranking, which covers every match. * fix(knowledge): hand only a large bounded set's first page to the GIN ranking Tin and GIN order candidates differently, so an offset advanced through one ranking cannot resume the other. A large bounded set's first page that Tin's widest window cannot fill goes to GIN; a later page stays with Tin and is left short as a narrow reader's is.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
There was a problem hiding this comment.
All reported issues were addressed across 35 files
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Fix all with cubic | Re-trigger cubic
…page was handed to it (#8110)
Uh oh!
There was an error while loading. Please reload this page.