Free tools Windows power users keep installed
One-click scans. No signup required.
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
If an app loads a list and then fetches related data separately for every item, it may be running an N+1 query pattern: one query for the list, followed by N more for relationships. The extra database calls can be hidden behind ordinary ORM attribute access, so the SQL log—not the apparent number of ORM calls—is the reliable way to spot them.
What is an N+1 query problem?
It is a database access pattern in which an application first fetches a set of records, then issues another query for related data as each record is accessed. The initial query is the “1”; the repeated relationship queries are the “N.”
For example, an application might retrieve 50 books in one query and then access each book’s unloaded author relationship. If the ORM issues a query for each author, the request makes 1 + 50 queries. Fifty is only an illustration: the actual count depends on the relationships accessed, query shape, caching, and ORM behavior.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
How lazy loading can create repeated queries
Lazy loading fetches related data only when code asks for it. That can be useful when the relationship is rarely needed. But if code accesses an unloaded relationship inside a loop, each access may trigger a database round trip, even though the code appears to be reading a property.
#1 Best Overall
Not every relationship access necessarily causes a new query. SQLAlchemy’s documentation notes that a simple many-to-one relationship can sometimes be resolved without a database round trip if the referenced object is already present in the current session. Whether a query occurs depends on the ORM’s state and the data already loaded.
How to recognize N+1 in SQL logs
Look for an initial SELECT that retrieves a group of parent records, followed by a succession of similar SELECT statements for related data. A common clue is that the repeated statements have the same structure while the parameter identifying the parent changes each time.
SQLAlchemy’s 2.0 tutorial recommends testing the application, enabling SQL echoing, and watching the emitted SQL as a first step. Framework query inspection and profiling facilities can also help. The important evidence is the statements actually sent to the database, including their parameters—not how many ORM calls appear in the source code.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →A focused diagnosis workflow
- Reproduce the slow request with representative data.
- Count and inspect the emitted statements, including repeated SQL and parameter values.
- Trace which relationship access triggers each repeated query.
- Apply a targeted loading strategy, then compare query count, rows returned, latency, and memory under the same conditions.
A lower query count does not by itself prove that a change is faster. Database plans, data volume, network latency, duplicated rows, and caching can affect the result. Compare the actual workload rather than relying on a universal speed claim.
Which loading strategy should you use?
Eager loading fetches related data as part of a planned query rather than waiting for each relationship to be accessed. It can prevent N+1 queries, but it has different query shapes. Choose based on whether the relationship is scalar or a collection, how many rows are involved, backend capabilities, and the SQL generated for the request.
| Approach | What it does | When it may fit | Trade-off |
|---|---|---|---|
| Joined eager loading | Adds a JOIN so related values arrive in the same result set. | Often useful for a needed scalar relationship or when combined rows suit the query. | Joining a collection can multiply result rows. Inspect the result shape and execution plan. |
| Select-in or batched loading | Issues a secondary SELECT that gathers related rows for selected parent identifiers, often using an IN clause. | Often a straightforward option for collections. | It still uses more than one statement. Composite keys with a backend that lacks tuple-IN support can make this strategy infeasible. |
| Subquery eager loading | Loads related values with a secondary query based on a subquery. | May fit particular relationship and query circumstances. | The subquery itself can have performance penalties depending on the database. |
| Raiseload guard | Raises an error when code attempts an unwanted lazy load. | Useful for surfacing unexpected relationship access during development or on controlled paths. | It is a guard, not a data-fetching optimization. Configure intended eager relationships explicitly. |
| Keep lazy loading | Fetches a relationship only when code accesses it. | Can suit data that is rarely needed. | Accessing the relationship in a loop over many records can produce N+1 queries. |
There is no universal “always join” fix. A JOIN may be efficient for one relationship and create substantial row duplication for another; a batched second query may be the better shape for a collection. Inspect the generated SQL and measure the relevant request.
Rank #4
SQLAlchemy examples
SQLAlchemy 2.1 documents relationship loading strategies including lazy, select-in, joined, and raise loading. The common option names include selectinload(), joinedload(), and raiseload(). For example, a query can specify a loading strategy with an ORM option:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →select(Book).options(selectinload(Book.author))
This illustrates the option’s form; adapt the entity and relationship names to your model and verify API details against the SQLAlchemy version in use. Joined loading uses a JOIN in the SELECT, while select-in loading collects parent identifiers and issues a secondary SELECT. SQLAlchemy 2.1 describes eager loading as its usual mitigation for N+1.
Best Value
Keep the fix tied to the request
A loading strategy should match the data a particular request needs. Load relationships that the response or page actually consumes, avoid fetching large collections unnecessarily, and retain lazy loading where access is genuinely rare. Recheck the statements and returned rows after changing the query: fixing repeated round trips should not silently replace them with an oversized or heavily duplicated result set.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

