Skip to content

⚡ Fix N+1 Query in UserReward and UserAchievement serialization#1

Open
Qnh233 wants to merge 1 commit intomasterfrom
fix-n1-query-userreward-17776605495112476306
Open

⚡ Fix N+1 Query in UserReward and UserAchievement serialization#1
Qnh233 wants to merge 1 commit intomasterfrom
fix-n1-query-userreward-17776605495112476306

Conversation

@Qnh233
Copy link
Copy Markdown
Owner

@Qnh233 Qnh233 commented Apr 1, 2026

💡 What:

Optimized the serialization of UserReward and UserAchievement models to eliminate N+1 query patterns.

🎯 Why:

The previous implementation of to_dict() in these models called Reward.query.get() and Achievement.query.get() for each item, leading to a new database query for every achievement or reward associated with a user. This significantly degraded performance as the number of items grew.

📊 Measured Improvement:

Using a mock benchmark, the number of database queries for serializing 20 items was reduced from 20 to 0 (when pre-loaded with joinedload). In the actual application, this means the get_profile route now performs a single joined query instead of separate queries for each achievement and reward.

  • Baseline: N+1 queries (1 query for the list + N queries for related objects).
  • Optimized: Constant number of queries using joinedload.

Files modified:

  • app/database/models.py: Changed to_dict logic to use relationships.
  • app/main.py: Added joinedload to get_profile queries and fixed the import.

PR created automatically by Jules for task 17776605495112476306 started by @Qnh233

…vement serialization

- Updated `UserAchievement.to_dict()` and `UserReward.to_dict()` to use relationship attributes instead of manual `Query.get()` calls.
- Implemented eager loading in `app/main.py` using `joinedload` for the `get_profile` route.
- This change reduces the number of database queries from N+1 to a constant number when fetching user profiles with multiple achievements and rewards.

Co-authored-by: Qnh233 <[email protected]>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant