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
[MB-8026] Optimizing FetchMany in query builder #6594
Conversation
…gainst EagerPreload naming assumptions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good to me! Admin interface seemed to be working as expected. TSPP data page is much faster and a lot less queries. Thanks for the clear Reviewer notes that really helped. I left a couple questions but I don't think it needs to hold up approval form my end. Might be good to get some other eyes on this if possible.
@@ -182,6 +182,12 @@ func (h ListMTOShipmentsHandler) Handle(params mtoshipmentops.ListMTOShipmentsPa | |||
queryFilters = []services.QueryFilter{ | |||
query.NewQueryFilter("move_id", "=", moveTaskOrderID.String()), | |||
} | |||
|
|||
// In some places, we used this unbound eager call accidentally and loaded all associations when the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we prefix this with TODO? Just wondering if that would help us find it later, which may not be true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I just added it.
@@ -26,8 +26,8 @@ type ReDomesticLinehaulPrice struct { | |||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"` | |||
|
|||
// Associations | |||
Contract ReContract `belongs_to:"re_contract"` | |||
DomesticServiceArea ReDomesticServiceArea `belongs_to:"re_domestic_service_area"` | |||
Contract ReContract `belongs_to:"re_contract" fk_id:"contract_id"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at all these fk_id
additions and I can't help but wonder if there are guidelines on when to add fk_id
to a model column. Or maybe we should always do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's this section from the Pop documentation. After working on several EagerPreload
efforts, I think it's probably better to always be explicit with the fk_id
than to let Pop figure it out. Eager
seems to have a different method for guessing the right field than EagerPreload
as I've gotten errors with EagerPreload
given the same model setup that don't happen with Eager
. The most recent thing I saw was that it tried to make transportation_offices
singular by changing it to something like transportation_officex
(and that only seemed to happen with EagerPreload
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of fk_id
is also mentioned in our Wiki as a workaround when the foreign key name is different from the relation name.
if associations == nil { | ||
return query | ||
} | ||
|
||
if associations.Preload() { | ||
return query.EagerPreload(associations.StringGetAssociations()...) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a test suite for the query builder? If so is it feasible to add a test or is this covered enough by other testing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some tests that get to this via FetchMany
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding tests! 🚀
Description
This PR begins to address two performance problems with our current implementation of
FetchMany
in the query builder:FetchMany
uses Pop'sEager
notEagerPreload
so it is making way more requests than it should.FetchMany
does not have a way to tell it you want to load zero associations. So it loads ALL associations.Reviewer Notes
NewQueryAssociation
was remapped to the newNewQueryAssociationPreload
in some places where preloading made sense and seemed to work fine.Eager
calls (which loaded all associations) tonil
to load no associations. This required changes to the query builder to support thenil
.fk_id
tohas_many
andbelongs_to
relationships so we don't have to rely on Pop's guesses for the field names (it was sometimes guessing wrong when preloading).FetchOne
as well to preload associations, but I got a lot of failures when doing so; we'll have to work through those if we want to make that change.FetchOne
probably needs a refactoring anyway as it is loading all associations every time and there's no way to change that behavior on a case-by-case basis. The good news is that sinceFetchOne
is fetching a single base record, default eager loading of associations doesn't cause an explosion of additional queries like it can be with a big list of base records (likeFetchMany
might have).has_many
association with a pointer-based foreign key (like we have when preloadingMTOServiceItems.ReService
for a shipment). I made a PR for Pop and it's been merged and is in Pop 5.3.4, but we have other issues it looks like we have to solve first before moving to that version.Setup
Code Review Verification Steps
References