Anchor selection and cardinality
Because expansion is free but the starting fan-out is not, the planner's real job is anchor selection by cardinality — begin from the end that pulls the fewest nodes into memory — and a single WHERE clause that changes which end is most selective will flip the plan's direction entirely.
Cypher hid one decision: which end of the pattern to start from. The planner makes it by estimating cardinality and anchoring on the few, not the many — and a WHERE clause can flip that choice and reverse the whole walk. But this entire optimization rests on an assumption: that every node has a SMALL, comparable number of edges. What happens when one node has ten million?
Scene 08
Anchor selection and cardinality
- Watch
- Try it
- Predict
- Capture
Same pattern as last scene: Alice's RATED movies. But now look at the two ends. Each one gets a number — an estimate of how many nodes that end pulls into memory. Alice rated about 12 movies. The movie she rated, The Matrix, was rated by about a million people. The chooser compares those two numbers and starts from the SMALLER end — Alice — then expands outward. Step through it.
Highlighted lines are the ones running in the diagram right now.
def estimate_ends(pattern):# cardinality estimate per BOUND end of the patternuser_end = stats.out_degree(pattern.user, ':RATED') # Alice ~12if pattern.where: # WHERE m.title = '...'movie_end = stats.selectivity(pattern.where) # pins ~1else:movie_end = stats.in_degree(pattern.movie, ':RATED') # ratersreturn {user_end, movie_end} # the numbers on the badges
def pick_anchor(pattern):ends = estimate_ends(pattern)# anchor on the SMALLEST estimated end — the few, not the manyanchor = argmin(ends, key=estimate)start = index_seek(anchor) # the one index lookup# expand AWAY from the anchor; direction follows the choicereturn expand(start, ':RATED', toward=other_end(pattern, anchor))
Where this sits in Build a graph database (Neo4j / Dgraph-style)
Scene 08 of 16, in the The language act — Cypher is a shape; the planner picks an anchor.. The planner's real job is to anchor on the most selective node and estimate cardinality — start from the few, not the many — so flipping a WHERE filter can flip which end is cheapest and reverse the whole traversal direction.
Up next. Anchor selection assumed degrees are roughly comparable — start from the end with the fewest edges. But real graphs have celebrities. The Rock has 232M followers. The instant a traversal has to EXPAND through that node, its relationship chain isn't a quick hop — it's millions of edges to scan, and the O(1)-per-hop promise dies on that one node.
All 16 scenes in Build a graph database (Neo4j / Dgraph-style) · Every curriculum