I'm working on a project where I have to collect a lot of data from the database. I'm using Symfony2 (symfony bf1281aebdc842a39ec0eb7438e1ea3fca9b9705) and Doctrine2 (doctrine 3b3186ee98392802a44118cd421a3530119aa7eaand ) as working base.
The Problem I encounter is, that I have to fetch about 15.000 articles. After that, I need to iterate through all of them an fetch more data on base of the article id (there are direct and indirect associations with i.e. (inherited) media or prices, etc...). It's ok for about 50-100 records, but if I want to use more records it takes a lot of ram an time to fetch everything from the database.
Is there a way to iterate through the data without using up all of the remaining ram? Is there a way to tell doctrine to stop using references?
Thank you in advance for any help!
In our entities we work with an array collection but Doctrine uses a persistent collection to lazy load our properties only when required. This is a mechanic of doctrine to improve performance and memory usage. Instead of using a set method, we are going to create methods for adding and removing categories or blog posts to our collections.
This relationship means that a blog post can have multiple categories. And categories can be used in multiple blog posts. As you can see we need a junction table for this. This junction tables links the blog posts with the correct categories. So how is the simplest and most correct way to do this in Doctrine 2 with entities?
If you try to return ArrayCollection then you will get the following error: So why is this? Well if we look deeper in the Doctrine classes we can find the following: Collection is an interface and we should use that instead. Use your interfaces and not your implementations!
From Doctrine's point of view, it is simply mapped as a unidirectional many-to-many whereby a unique constraint on one of the join columns enforces the one-to-many cardinality. The following example sets up such a unidirectional one-to-many association:
save another line by using:
$iterableResult = $doctrine->getManager()->createQuery("SELECT c FROM ENTITY c")->iterate();
while ((list($obj) = $iterableResult->next()) !== false) {
// do something with $obj
$em->detach($obj);
}
You can look into using iterative (step-by-step) hydration in Doctrine:
$em = $this->getDoctrine()->getEntityManager();
$q = $em->createQuery("<DQL to select the objects I want>");
$iterableResult = $q->iterate();
while (($row = $iterableResult->next()) !== false) {
// do stuff with the data in the row, $row[0] is always the object
$em->detach($row[0]); // detach from Doctrine, so that it can be GC'd immediately
}
Details from this article, under Mass object processing
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With