Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

N+1 Queries with Joins("Company").Preload("Company.Addresses") on Addresses #6988

Closed
alexisvisco opened this issue Apr 23, 2024 · 0 comments · Fixed by #6990
Closed

N+1 Queries with Joins("Company").Preload("Company.Addresses") on Addresses #6988

alexisvisco opened this issue Apr 23, 2024 · 0 comments · Fixed by #6990
Assignees
Labels
type:with reproduction steps with reproduction steps

Comments

@alexisvisco
Copy link
Contributor

alexisvisco commented Apr 23, 2024

GORM Playground Link

go-gorm/playground#722

Version

Superior to v1.25.6

Description

This issues to demonstrate an issue in GORM's query behavior.

The function illustrates potential inefficiencies and unexpected results that may have been introduced due to a previous fix in GORM's preloading and join operations.

Background

Previously, a fix was implemented in GORM to address an issue where, when joining on Account.Pet and then preloading Account.Companies, the account was loaded twice, even though it was already present in the main query. This fix aimed to improve the consistency and efficiency of the query process.

Current Issue

However, the provided playground suggests that the fix may have unintentionally introduced another issue. The test highlights the following:

Unexpected Queries: The function is expected to execute two queries (one for fetching user data and another for related data). Instead, there may be an additional, unnecessary query, suggesting an n+1 query problem.

TLDR:

DB.Joins("Company").Preload("Company.Addresses").Find(&result).Error

is resulting in

2024/04/23 15:08:19 /Users/alexisviscogliosi/dev/go-playground/db.go:59
[1.205ms] [rows:2] SELECT * FROM "addresses" WHERE "addresses"."company_id" = 1

2024/04/23 15:08:19 /Users/alexisviscogliosi/dev/go-playground/db.go:59
[0.634ms] [rows:2] SELECT * FROM "addresses" WHERE "addresses"."company_id" = 2

2024/04/23 15:08:19 /Users/alexisviscogliosi/dev/go-playground/db.go:59
[3.667ms] [rows:2] SELECT "users"."id","users"."created_at","users"."updated_at","users"."deleted_at","users"."name","Company"."id" AS "Company__id","Company"."name" AS "Company__name","Company"."user_id" AS "Company__user_id" FROM "users" LEFT JOIN "companies" "Company" ON "users"."id" = "Company"."user_id

Note: if there is more than 2 companies it results in N queries where N is the number of companies.

Instead of

SELECT `users`.`id`,`users`.`created_at`,`users`.`updated_at`,`users`.`deleted_at`,`users`.`name`,`Company`.`id` AS `Company__id`,`Company`.`name` AS `Company__name`,`Company`.`user_id` AS `Company__user_id` FROM `users
		LEFT JOIN `companies` `Company` ON `users`.`id` = `Company`.`user_id`
		WHERE `users`.`deleted_at` IS NULL
SELECT * FROM `companies` WHERE `companies`.`id` IN (1, 2)

In version v1.25.6 the select of addresses where using a IN clause but have the problem of doing a second query with companies (#6715 (comment))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:with reproduction steps with reproduction steps
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants