Writing Efficient Queries
Introduction
Welcome back to the Indexes and Performance course! We have reached the final lesson of this unit, where we bring together everything we have learned about indexes and performance optimization. In previous lessons, we created property indexes and explored compound indexes. Now, we will focus on writing queries that make the most of these optimizations.
Even with perfect indexes in place, the way we structure our queries can dramatically impact performance. In this lesson, we will examine practical patterns for writing efficient queries, understand when to filter data, and learn techniques that help Neo4j's query planner do its best work.
Query Efficiency: Why Structure Matters
Before diving into specific patterns, let's understand why query structure matters even when indexes exist. Neo4j's query planner makes decisions based on how we write our queries, including when to use indexes, when to filter data, and how to order operations. Two queries that produce the same result can have very different performance characteristics.
The key principle is reducing cardinality early: we want to minimize the number of rows (or records) flowing through our query pipeline as soon as possible. This means filtering, limiting, and using indexes before performing expensive operations like traversing relationships, sorting large result sets, or aggregating data.
Property Matching: Index-Friendly Patterns
Let's start by examining two common ways to filter nodes by property values. Both approaches work, but one creates a more direct path to using our indexes:
This inline property matching syntax tells Neo4j exactly what we are looking for. When an index exists on :User(name), the query planner can immediately recognize this as an index seek operation. The syntax is concise and makes our intent clear: find the specific user with this name.
Here is what this query returns:
