You are currently viewing the 0.10 branch manual.   Switch to 0.11

0.10 User Manual

0.10 User Manual

Chapter 15 Caching

15.1 Introduction

Doctrine_Cache offers an intuitive and easy-to-use query caching solution. It provides the following things:

  • Multiple cache backends to choose from (including Memcached, APC and Sqlite)
  • Advanced options for fine-tuning. Doctrine_Cache has many options for fine-tuning performance.

Initializing a new cache driver instance:

Listing 15.1

<?php

$cacheDriver = new Doctrine_Cache_Memcache($options);

?>

15.2 Drivers

15.2.1 Memcache

Memcache driver stores cache records into a memcached server. Memcached is a high-performance, distributed memory object
caching system. In order to use this backend, you need a memcached daemon and the memcache PECL extension.

Listing 15.2

<?php

// memcache allows multiple servers
$servers = array('host' => 'localhost',
                 'port' => 11211,
                 'persistent' => true);

$cacheDriver = new Doctrine_Cache_Memcache(array('servers' => $servers,
                                           'compression' => false));

?>

Available options for Memcache driver:

Option Data Type Default Value Description
servers array array(array('host' => 'localhost','port' => 11211, 'persistent' => true))

servers ; each memcached server is described by an associative array : 'host' => (string) : the name of the memcached
server, 'port' => (int) : the port of the memcached server, 'persistent' => (bool) : use or not persistent connections
to this memcached server ||

compression boolean false true if you want to use on-the-fly compression

15.2.2 APC

The Alternative PHP Cache (APC) is a free and open opcode cache for PHP. It was conceived of to provide a free, open, and
robust framework for caching and optimizing PHP intermediate code.

The APC cache driver of Doctrine stores cache records in shared memory.

Listing 15.3

<?php

$cacheDriver = new Doctrine_Cache_Apc();

?>

15.2.3 Db

Db caching backend stores cache records into given database. Usually some fast flat-file based database is used (such as
sqlite).

Initializing sqlite cache driver can be done as above:

Listing 15.4

<?php

$conn  = Doctrine_Manager::connection(new PDO('sqlite::memory:'));

$cacheDriver = new Doctrine_Cache_Sqlite(array('connection' => $conn));

?>

15.3 Query Cache & Result Cache

15.3.1 Introduction

Doctrine provides means for caching the results of the DQL parsing process, as well as the end results of DQL queries (the
data). These two caching mechanisms can greatly increase performance. Consider the standard workflow of DQL query execution:

  1. Init new DQL query
  2. Parse DQL query
  3. Build database specific SQL query
  4. Execute the SQL query
  5. Build the result set
  6. Return the result set

Now these phases can be very time consuming, especially phase 4 which sends the query to your database server. When
Doctrine query cache is being used only the following phases occur:

  1. Init new DQL query
  2. Execute the SQL query (grabbed from the cache)
  3. Build the result set
  4. Return the result set

If a DQL query has a valid cache entry the cached SQL query is used, otherwise the phases 2-3 are executed normally and
the result of these steps is then stored in the cache.
The query cache has no disadvantages, since you always get a fresh query result. You should therefore always use it in a
production environment. That said, you can easily use it during development, too. Whenever you change a DQL query and
execute it the first time Doctrine sees that is has been modified and will therefore create a new cache entry, so you
dont even need to invalidate the cache. It's worth noting that the effectiveness of the query cache greatly relies on
the usage of prepared staments (which are used by Doctrine by default anyway). You should not directly embed dynamic
query parts and always use placeholders instead.

When using a result cache things get even better. Then your query process looks as follows (assuming a valid cache entry
is found):

  1. Init new DQL query
  2. Return the result set

As you can see, the result cache implies the query cache shown previously.
You should always consider using a result cache if the data returned by the query does not need to be up-to-date at any
time.

15.3.2 Query Cache

15.3.2.1 Using the query cache

You can set a connection or manager level query cache driver by using Doctrine::ATTR_QUERY_CACHE. Setting a connection
level cache driver means that all queries executed with this connection use the specified cache driver whereas setting
a manager level cache driver means that all connections (unless overridden at connection level) will use the given cache
driver.

Setting a manager level query cache driver:

Listing 15.5

<?php

$manager = Doctrine_Manager::getInstance();

$manager->setAttribute(Doctrine::ATTR_QUERY_CACHE, $cacheDriver);

?>

Setting a connection level cache driver:

Listing 15.6

<?php

$manager = Doctrine_Manager::getInstance();
$conn    = $manager->openConnection('pgsql://user:pass@localhost/test');

$conn->setAttribute(Doctrine::ATTR_QUERY_CACHE, $cacheDriver);

?>

15.3.2.2 Fine-tuning

In the previous chapter we used global caching attributes. These attributes can be overriden at the query level. You can
override the cache driver by calling useQueryCache with a valid cacheDriver. This rarely makes sense for the query cache
but is possible:

Listing 15.7

<?php

$query = Doctrine_Query::create()
          ->useQueryCache(new Doctrine_Cache_Apc());

?>

15.3.3 Result Cache

15.3.3.1 Using the result cache

You can set a connection or manager level result cache driver by using Doctrine::ATTR_RESULT_CACHE. Setting a connection
level cache driver means that all queries executed with this connection use the specified cache driver whereas setting a
manager level cache driver means that all connections (unless overridden at connection level) will use the given cache
driver.

Setting a manager level cache driver:

Listing 15.8

<?php

$manager = Doctrine_Manager::getInstance();

$manager->setAttribute(Doctrine::ATTR_RESULT_CACHE, $cacheDriver);

?>

Setting a connection level cache driver:

Listing 15.9

<?php

$manager = Doctrine_Manager::getInstance();
$conn    = $manager->openConnection('pgsql://user:pass@localhost/test');

$conn->setAttribute(Doctrine::ATTR_RESULT_CACHE, $cacheDriver);

?>

Usually the cache entries are valid for only some time. You can set global value for how long the cache entries should
be considered valid by using Doctrine::ATTR_RESULT_CACHE_LIFESPAN.

Listing 15.10

<?php

$manager = Doctrine_Manager::getInstance();

// set the lifespan as one hour (60 seconds * 60 minutes = 1 hour = 3600 secs)
$manager->setAttribute(Doctrine::ATTR_RESULT_CACHE_LIFESPAN, 3600);

?>

Now as we have set a cache driver for use we can make a DQL query to use it:

Listing 15.11

<?php

$query = Doctrine_Query::create();

// fetch blog titles and the number of comments
$query->select('b.title, COUNT(c.id) count')
      ->from('Blog b')
      ->leftJoin('b.Comments c')
      ->limit(10)
      ->useResultCache(true);

$entries = $query->execute();

?>

15.3.3.2 Fine-tuning

In the previous chapter we used global caching attributes. These attributes can be overriden at the query level. You can
override the cache driver by calling useCache with a valid cacheDriver:

Listing 15.12

<?php

$query = Doctrine_Query::create();

$query->useResultCache(new Doctrine_Cache_Apc());

?>

Also you can override the lifespan attribute by calling setResultCacheLifeSpan():

Listing 15.13

<?php

$query = Doctrine_Query::create();

// set the lifespan as half an hour
$query->setResultCacheLifeSpan(60 * 30);

?>

Comments (2) [ add comment ]

Write reset the cache? - Posted by Blackshack about 3 months ago.

Hello, i wrote a framework for a project using Doctrine like ORM, and i have a question about the cache.
You explain how the system react when you make a select query, but what appends if you have a query which is a insert or update SQL commands??
The cache manager analyze the data concerned by update and make relation with select result cached or not??
and if not there is a method to manually reset the cache for a specifique query??

Thanks -and thanks for Doctrine -

Result Cache - Posted by Lee about about 1 month ago.

I wouldn't recommend using the result caching feature right now. From looking at the code and trying to use it, it is broken in several ways. You always get back an array, even if you want a Doctrine_Collection. I also has no provision for invalidating cache entrie to maintain cache/db consistency. I know they tell you that it is only for data that doesn't have to be up to data, but it really isn't a big jump to make it Component aware. It also is caching things other than SELECTS, which is kinda stupid. Don't get me wrong, I love Doctrine, it's just a bit of a brain dead result cache solution.

Add Comment

Add New Comment
Please enter 'follow the doctrine' without the quotes