Repository navigation
perf(planner): count two-hop paths over undirected hops - #132
Merged
Merged
Conversation
Deploying lance-csr with
|
| Latest commit: |
c86627d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://b3a25789.lance-csr.pages.dev |
| Branch Preview URL: | https://perf-count-undirected-hops.lance-csr.pages.dev |
prrao87
marked this pull request as ready for review
November 7, 2026 02:28
Undirected hops kept the join plan in both counting rewrites. Count them from edges too: an undirected hop's rows at the middle node are its neighbours either way round, and for same-type hops the planner's distinct-edges predicate, which compares endpoints in both orders, then excludes exactly the pairs with the same far end, which the shared-end correction already subtracts. Recognise the predicate by the nodes it makes equal rather than by one fixed shape.
prrao87
force-pushed
the
perf/count-undirected-hops
branch
from
November 7, 2026 02:31
b00fc09 to
c86627d
Compare
This was referenced Nov 7, 2026
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.
Why
Both counting rewrites, the two-hop count and the first-hop count grouped per node, gave up on any undirected hop, so
MATCH (a)-[:FOLLOWS]-(b)-[:FOLLOWS]-(c) RETURN count(*)orRETURN b.id, count(a)over(a)-[:FOLLOWS]-(b)built every path or row before counting it. This is half of the "undirected hops andOPTIONAL MATCH" item in #78. Builds on #131 (merged), whose correction it reuses.What changed
bareb's neighbours either way round (a self-loop once, as the engine matches it), and its mean fan-out is the sum of both directions'.RETURN b.name, count(a)over(a)-[:R]-(b)...) also accepts an undirected first hop, and on the CSR still counts it in place.Validation
cargo test --workspace,cargo clippy --workspace --all-targets -- -D warningsandcargo fmt --all --checkpass.make test(1710 passed) andmake lintpass, as dozensical build --strictandtypos. CI is pending.New tests check the count against the join plan and against hand-counted answers: undirected hops of different types, of the same type, and mixed with a directed hop; an undirected self-loop; edges joining the same two nodes in both directions, which never pair up; a filter on one hop; and an undirected first hop counted per node on the CSR, in place.
graph-benchmark (100K
Person, 2.4MFOLLOWS, in memory), median ms as in perf(planner): count same-type two-hop paths that share an end #131; Apple M5, 24 GB, macOS 26.6.2; release wheels built from each commit and loaded withuv run --with. Answers are equal across builds and engines. "Before" is the shared-end branch this stacks on.(a)-[:FOLLOWS]-(b)-[:FOLLOWS]-(c) RETURN count(*)(a)-[:FOLLOWS]-(b)-[:HAS_INTEREST]->(i) RETURN count(*)(a)-[:FOLLOWS]-(b) RETURN b.id, count(a), top 3Both suites (GDC SF1, graph-benchmark-ldbc 3afadb9 and graph-benchmark-ldbc-complex fc7b44c, both modes): the physical plan of every query, captured through
explain()for each wheel, is the same as onmainfor this branch, except that IC3's inline{name, type}map prints its two filters in the other order, an ordering that changes between builds. None of their queries has this shape, so their timings can't change through it; the suites were timed once for the top of this stack, in perf(planner): count two-hop paths whose second hop is optional #133, every test passing.Part of #78.
🤖 Generated with Claude Code