You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ok, I know those limits were discussed in depth in #10305 and #10371, and I agree with comments that having too much of IDs inside IN() statement is a bad idea, however, I don't agree with the conclusion to not do anything.
The concern raised was that building up lots of models takes lots of memory and there are risks of having memory overflow exceptions. But if we don't do that, Yii2 fails miserably when trying to pull models with a total number more than the underlying database allows inside IN() statement. So it either always fails because of the database limitation not accounted properly in Yii2, or sometimes fails if memory thresholds for PHP are reached. Why was it decided for the former instead of a later?
As of now I just don't see any legal workarounds against that issue. I have a huge relational hierarchy defined in my application. The logic pulls 1 root model (e.g. a blog post), and then it tries to pull lots of other related things, such as comments, authors, etc, via relations. On a very rare occasion, the number of comments goes beyond 1000 at which point the logic fails to pull models related to those comments and linked via a comment primary key, and in the end, the blog post cannot be displayed. I cannot batch the comments, because those are being pulled indirectly (through relations), rather than directly, thus they are always resolved with all().
I don't want to manage comments separately from the blog post, e.g. I don't want that:
$comments = $post->getComments()->all();
Because in the above case comments are not present from within the parent model $post, and have to be resolved again if they are accessed again.
I want to handle comments and all models related to comments like that:
$comments = $post->comments;
And I want all comments on the same page, no pagination. This is a design decision, and we can discuss in length whether it is correct or not, but right now, I just don't see how to do that in Yii2 without hacks.
I personally believe it is better to hit potential memory thresholds when trying to construct thousands of models, rather than allow a database exception from unaccounted database limitations.
Oh, and speaking of hacks, I had to change ActiveRelationTrait class to break IN() statements in batches of 1000 items to workaround the issue (in case anyone still wants to have that functionality):
The above results in related models resolved via a single query where model keys are split by 1000 items and glued together via OR.
I actually wouldn't mind supporting this change in a legal way (like extending some base class and then passing my custom class to a configuration array), but there are no hooks available.
@dryu thank you for the detailed description of your POV.
I personally believe it is better to hit potential memory thresholds when trying to construct thousands of models, rather than allow a database exception from unaccounted database limitations.
The problems start to appear when I reference a model relative to comments, e.g. in the example above it is comments.time. When Yii2 tries to retrieve that, it runs the query:
SELECT*FROM CommentsTime WHERE comment_id IN (...)
And there goes all ids of all comments retrieved prior to that.
Ok, I know those limits were discussed in depth in #10305 and #10371, and I agree with comments that having too much of IDs inside
IN()
statement is a bad idea, however, I don't agree with the conclusion to not do anything.The concern raised was that building up lots of models takes lots of memory and there are risks of having memory overflow exceptions. But if we don't do that, Yii2 fails miserably when trying to pull models with a total number more than the underlying database allows inside
IN()
statement. So it either always fails because of the database limitation not accounted properly in Yii2, or sometimes fails if memory thresholds for PHP are reached. Why was it decided for the former instead of a later?As of now I just don't see any legal workarounds against that issue. I have a huge relational hierarchy defined in my application. The logic pulls 1 root model (e.g. a blog post), and then it tries to pull lots of other related things, such as comments, authors, etc, via relations. On a very rare occasion, the number of comments goes beyond 1000 at which point the logic fails to pull models related to those comments and linked via a comment primary key, and in the end, the blog post cannot be displayed. I cannot batch the comments, because those are being pulled indirectly (through relations), rather than directly, thus they are always resolved with
all()
.I don't want to manage comments separately from the blog post, e.g. I don't want that:
Because in the above case comments are not present from within the parent model $post, and have to be resolved again if they are accessed again.
I want to handle comments and all models related to comments like that:
And I want all comments on the same page, no pagination. This is a design decision, and we can discuss in length whether it is correct or not, but right now, I just don't see how to do that in Yii2 without hacks.
I personally believe it is better to hit potential memory thresholds when trying to construct thousands of models, rather than allow a database exception from unaccounted database limitations.
Oh, and speaking of hacks, I had to change
ActiveRelationTrait
class to break IN() statements in batches of 1000 items to workaround the issue (in case anyone still wants to have that functionality):The above results in related models resolved via a single query where model keys are split by 1000 items and glued together via OR.
I actually wouldn't mind supporting this change in a legal way (like extending some base class and then passing my custom class to a configuration array), but there are no hooks available.
What steps will reproduce the problem?
What is the expected result?
All 1000+ comments to be pulled and available via
$blog->comments
.What do you get instead?
Additional info
The text was updated successfully, but these errors were encountered: