cache lazy loaded objects

Hi all !

Im in a situation where a it takes much longer time to join all relations with the "with" command

eg


$product = Product::model()->with( 'accessories', 'prices')->findbyPk( $id!==null ? $id : $_GET['id'] );

lazy loading is faster but then I cant cache the object when fully populated

eg in my controller




   public function actionViewProduct($id = null)

    {

    	    	

		$product=Yii::app()->datacache->get('product'.$id);

		if( $product===false )

		{    	    

			print ("fetching");	

    		$product = Product::model()->findbyPk( $id!==null ? $id : $_GET['id'] );

			Yii::app()->datacache->set('product'.$id, $product, 30);

		}

    	

    	$this->render('viewProduct',array(

			'product'=>$product,		

		));

    }



Does anyone have any ideas ?

So you want lazy loading and you want to cache the whole post model (with all related models).

Why not access (lazy-load) the related models before caching?

Also maybe this can help?

Sure i can touch the related models in the controller but it seems like an ugly approach

The together option looks interesting, but I get some problems.

When I in the relations of the model declare:




	public function relations()

	{

		return array(

			'prodaccessories' => array(self::HAS_MANY, 'ProdAccesssory', 'headsku', 'together'->false),

		);

	}



and then do a




$product = Product::model()->with('prodaccessories')->findbyPk( $id );



i get a Fatal error: Allowed memory size of 134217728 bytes exhausted

can someone please advice

Looks like you ran out of memory for that query. How many prodaccessories are you pulling? If it’s over 50 or so you should probably not use AR for this case

really 50 ?

it like a couple of 100:s, but it works using regular lazy loading or with just the with() command then its sending back like 3000 rows. what is the outcome of using the together->false option I thought it would be an additional query much like when you use lazy loading ?

I guess I just have to touch the related models in the controller before I save them to the cache.

// Wrote something wrong here

Can you say something about the speed difference between eager/lazy-loading? I’m just wondering does it take several seconds longer or is lazy-loading just marginal faster?

Lazy-loading is much slower when you are pulling many records with related objects.

Imagine you are pulling 50 rows and each row has 2 related objects

With lazy-loading, this would mean 101 (50+50+1) queries are performed. With eager loading, only 1 query is performed.

If you’re using AR however, yii will be filling 150 (50+50+50) active records either way.

Thanks for all the answers, my model is more complicated then in my example … but there is a significant decrease in performance when using the eager loading approach.

What jonah said is pretty logic and that’s why I was asking about speed-difference. How you measure the performance? Note if you not access all relations, lazy-loading could be faster of course. Also in debug mode you will see a huge performance decrease when using many relations. Try to test in production mode in this case.

In actionViewProduct() you only retrieve one product without related data. Are you sure the view accesses all the related data? What are all the queries performed in each case? BTW, I don’t think caching helps anything with the way you are doing it. I don’t think the cache is faster than a DB query. Usually you use the cache to cache calculations performed, not just database rows