-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
DDC-3905: Eager fetching yields N+1 queries in *ToMany associations when using DQL #4762
Comments
I also suffer from this behavior. Are any workarounds there? |
@Trainmaster the current workaround is doing fetch joins or multi-step hydration ( http://ocramius.github.io/blog/doctrine-orm-optimization-hydration/ ) I am not aware of any work being done to implement this particular feature |
Any update on this? |
Also interested in this. |
I would love to see this fixed. Personally, I've also come to a place where I rarely use eager loading and rarely provider getters for automatically retrieving the contents of a collection, produced by an Do, however, remember that some database systems have a limit to the number of elements allowed in a list. E.g. Firebird's (https://firebirdsql.org/) 1499 list element limit. See: https://www.ibphoenix.com/resources/documents/general/doc_323 Next, there's the query size in pure bytes to consider, e.g. MySQL's If this hydration issue ever gets fixed, I'd recommend from the get go, that this is performed in chunks. Suggested chunked hydration Add a new method, protected int $collectionChunkSize = 2000;
...
public function getCollectionChunkSize(): int
{
return $this->collectionChunkSize;
} This value may of course vary depending on the platform/database system. The value should be changeable during the configuration stage of the DBAL. The chunked fetching will then be performed as such: $ids = [...]; // A list of n IDs, which may be integers, UUIDs, SHA256, etc.
foreach (array_chunk($ids, $platform->getCollectionChunkSize()) as $chunk) {
...
$queryBuilder->andWhere($queryBuilder->expr()->in('entity.id', $chunk)); // Or something safer, e.g. using parameters, to avoid potential for 2nd order SQL injection
...
} |
Any updates on this? Don't let Laravel be better... 😄 |
@kgasienica propose a patch - if you haven't seen updates, asking for updates is redundant, no? :) |
Hi, While there is room for improvement, this is not a roadblock for your system. I always advise people to never use fetch="EAGER" as it leads to N+1 problem. You can solve it by running¨ One to One example:
Many to One example:
Aside from this solution, we would welcome contributions for batching support on eager associations. Thanks, |
Actually this thread is about *ToMany associations. There is no simple solution for such associations. You can build such a query, but if there are multiple *Many assosiactions, it will be too slow. |
See proposed solution above: #4762 (comment) It requires manual work, but that's how multi-step hydration works there |
I read this one, but partial objects are deprecated #8471 |
I created a PR for subselect fetch a while ago that might fix this. Am on mobile so cant eaily find the PR id here |
Regarding multi-step hydration (kudos @Ocramius for the excellent blog post!) a slight issue is that partial objects have been deprecated in #8471. I completely understand why partial objects are a bad idea. They are, however, helpful in queries like (quoting from Marco's blog)
The second query avoids loading the
which is a regular fetch-join that will initialize the |
Jira issue originally created by user benjamin:
I have an entity with all kinds of associations:
I have tested using
fetch="EAGER"
on each of these associations, and running a DQL query against the entity.For both
OneToOne
andManyToOne
, the SQL log looks like:Which is exactly 2 queries whatever the number of entities. This is all good.
However, for
OneToMany
the SQL log looks like:And for
ManyToMany
the SQL log looks like:Eager loading
OneToMany
andManyToMany
results in N+1 queries, so there's no point eager loading them at all.Is this a bug, or a known limitation?
What prevents Doctrine from using a
WHERE IN ()
and a single, second query?The text was updated successfully, but these errors were encountered: