Pages

Thursday, October 17, 2013

Cakephp-Query and Cache Optimization

Recently while working for a technical client I learnt a lot of things regarding optimization of a cakephp site
which I am discussing as follows

1. Cache regularly used queries in cache.Queries regarding listing Menu's which are listed on every page footer item's,header item's should be cached.

For example if you are showing a list of categories in Menu from database.You must cache those so same query is not run again and again on same page

I cached as follows

 $mainCategories = Cache::read('Categories','long_db');  
         if (!$mainCategories)   
         {  
           $mainCategories = $this->Category->find('all', array('conditions' => array(''),'fields'=>array(''),'order'=>array('')));  
           Cache::write('Categories',$mainCategories,'long_db');  
         }  

2. In AppModel add

 public $recursive = -1;  
    function find($conditions = null, $fields = array(), $order = null, $recursive = null) {  
     $doQuery = true;  
     // check if we want the cache  
     if (!empty($fields['cache'])) {  
       $cacheConfig = null;  
       // check if we have specified a custom config  
       if (!empty($fields['cacheConfig'])) {  
         $cacheConfig = $fields['cacheConfig'];  
       }  
       $cacheName = $this->name . '-' . $fields['cache'];  
       // if so, check if the cache exists  
       $data = Cache::read($cacheName, $cacheConfig);  
       if ($data == false) {  
         $data = parent::find($conditions, $fields,  
           $order, $recursive);  
         Cache::write($cacheName, $data, $cacheConfig);  
       }  
       $doQuery = false;  
     }  
     if ($doQuery) {  
       $data = parent::find($conditions, $fields, $order,  
         $recursive);  
     }  
     return $data; 
    } 

Now what we have done here is
a. In first line we have added recursive=-1 so cake will no longer fetch 1st level relationships by default and they can be acquired by manually setting when required thus reducing over load.
b. In the second line we have added a function which will allow you to cache your queries even without writing the code in step one it automates the process as follows


 $this->User->find('list',  
   array('cache' => 'userList', 'cacheConfig' => 'short')  
 );  

This will automatically cache your query's when it finds cache and cacheConfig parameter's in find condition

Make sure following is enabled and added in "/app/Config/core.php"

 Configure::write('Cache.check', true);  
 Cache::config('short', array(  
   'engine' => 'File',  
   'duration'=> '+5 minutes',  
   'probability'=> 100,  
   'path' => CACHE,  
   'prefix' => 'cache_short_'  
 ));  


The second statement is a cache configuration defined in core.You can also set another configuration and pass the same to "cacheConfig" parameter's above like we have passed "short"

3. Bind/Unbind Model's on Fly

This requires proper requirement analysis and analyzing ERD the way it reflects on project.
One way out is that if you feel if the binding between 2 model's is required at every step

For example Menu categories and subcategories are required so it is very much feasible to join them together at the beginning only.So if at any point you require only categories you should unbind the subcategories relation.

It's very hard to judge which way to follows to Bind all model's first and then unbind on fly to taste or vice versa.I prefer a mix approach i.e. when in doubt I prefer to bind on fly rather than to load an unnecessary association on fly

No comments:

Post a Comment