Repository navigation
perf(search): trigram index for substring name search - #2347
Draft
gtarpenning wants to merge 1 commit into
Draft
gtarpenning wants to merge 1 commit into
gtarpenning wants to merge 1 commit into
Conversation
Substring lookups (`name LIKE '%x%'`) scanned every node. A trigram FTS5 table (migration 12) now prefilters them when the token is 3+ chars with no LIKE wildcard; the original LIKE still decides the result. The table is skipped on Node builds without FTS5 and healed by the next bulk load. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
name LIKE '%x%'cannot use a B-tree, so every substring lookup scans all nodes. The prompt hook is a fresh process per prompt and runs several of these each time, so the scan cost is paid on every prompt. This adds a trigram FTS5 index (nodes_tri) and uses it to narrow the candidates.Independent of the cross-process memo PR; either can merge first. #2115 and #2260 touch nearby code in
queries.ts.What changed
nodes_tri(name, qualified_name), an external-content FTS5 table overnodeswithtokenize='trigram', plus insert/delete/update triggers beside thenodes_ftsones. Fresh databases get it fromschema.sql.findNodesByNameSubstringandsearchNodesLikeaddrowid IN (SELECT rowid FROM nodes_tri ...)when the token is 3+ characters and has no_or%. The originalLIKEstays in the query, so the index only narrows candidates and result sets are unchanged. Shorter or wildcard tokens take the old path.schema.sqlinstead of a hard-coded name list, so the heal after an interrupted bulk load covers both.LIKE. A later bulk load on an FTS5 build creates the table.Measured
Warm query time on a large TS/Go/Python monorepo index (about 1.5 GB, 350k nodes, 1.2M edges):
name LIKE)Result sets were identical for every token tried (compared by rowid). Tokens under 3 characters stay on the scan path, where the index is no faster.
nodes_triadds about 2.5-3.7% to the database (55 MB on 1.5 GB).Compatibility
nodes_tricurrent, and they never query it.nodes_triuntil the next bulk load on a build that has it; substring search stays correct throughout.Testing
npx tsc --noEmitnpx vitest run __tests__/trigram-substring.test.ts __tests__/fts5-fallback.test.ts: results match aLIKEscan; a node removed fromnodes_trialone disappears from long-token results, so the index is consulted (the test fails with the prefilter reverted); a v11 database without FTS5 opens and falls back toLIKE.npx vitest run: 5748 passed, 20 failed. The 20 are indaemon-older-version,daemon-registryandindex-command, and fail the same way on unmodifiedmain.🤖 Generated with Claude Code