select_related
select_related solves the N+1 query problem by fetching related objects in a single JOIN query.
The Problemโ
# N+1 queries!
posts = await Post.objects.filter(active=True)
for post in posts:
print(post.author.name) # Each access triggers a new query
The Solutionโ
from ryx.relations import apply_select_related
# Single query with JOIN
posts = await Post.objects.filter(active=True)
posts = await apply_select_related(posts, fields=["author"])
for post in posts:
print(post.author.name) # No extra queries
How It Worksโ
select_related reconstructs the query with LEFT JOIN:
-- Without select_related
SELECT * FROM "posts" WHERE "active" = ?
-- With select_related(["author"])
SELECT "posts".*, "authors".* FROM "posts"
LEFT JOIN "authors" ON "posts"."author_id" = "authors"."id"
WHERE "posts"."active" = ?
The Rust executor decodes the joined rows and reconstructs full model instances with related objects attached.
Multiple Relationsโ
posts = await Post.objects.filter(active=True)
posts = await apply_select_related(posts, fields=["author", "category"])
When to Use select_relatedโ
- ForeignKey relationships โ Always works
- OneToOne relationships โ Always works
- When you know you'll access the related object
- When the related table is small (JOINs are cheap)
When NOT to Use select_relatedโ
- ManyToMany relationships โ Use
prefetch_relatedinstead - When you won't access the related object (wasted JOIN)
- When the related table is huge (JOINs are expensive)
Next Stepsโ
โ prefetch_related โ Eager loading for M2M