2

I think I'm getting crazy, I'm trying to implement Zend_Cache to cache my database query. I know how it works and how to configure.

But I can't find a good way to set the Identifier for the cache entries. I have a method which searches for records in my database (based on an array with search values).

/**
 * Find Record(s)
 * Returns one record, or array with objects
 *
 * @param array   $search Search columns => value
 * @param integer $limit  Limit results
 * @return array One record , or array with objects
 */
public function find(array $search, $limit = null)
{
    $identifier = 'NoIdea';

    if (!($data = $this->_cache->load($identifier))) {
        // fetch
        // save to cache with $identifier..
    }

But what kind of identifier can use in this situation?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
opHASnoNAME
  • 20,224
  • 26
  • 98
  • 143

4 Answers4

3

The identifier should be a unique string to represent the cache entry.

You might like to name them based on your database tables and fields, e.g. db_tablename_primarykey_1

If you have a method with several arguments, it'll be a pain to make a string containing all of them. Alternatively you can concat a function's arguments and the db_tablename to produce a string for hashing. For example:

$identifier = md5('db_tablename_find' . serialize(func_get_args()));
David Snabel-Caunt
  • 57,804
  • 13
  • 114
  • 132
1

You may want to consider using Function frontend for Zend Cache, where you can do something like this:

$cache->call('veryExpensiveFunc', $params);

and the key would be produced automatically (could be a long-ish one, though). You may use Class frontend which would allow you to cache all methods of the class, transparently.

StasM
  • 10,593
  • 6
  • 56
  • 103
1

I'm having this same issue. I don't know if you found a solution yet but i have a temporary solution (because it's not very efficient):

  1. Create a cache directory for each table you are going to query and cache results.

  2. Whenever you query that table, save the result using a unique id. Here's the problem with my solution. You can't use the query as an id since it may be too long and some operating systems may reject it. So what i came up with is to store all queries in another file along with an auto-incrementing id, like this:

    0->>SELECT * FROM table
    1->>SELECT * FROM table WHERE foo = bar
    

You get the idea. So before executing the query check that file to see if the current query is there, if present, get the id and load using that id. You can store this file in the same cache directory.

  1. Whenever you update, insert or delete data in that table simply clean the cached records like this: $cache->clean('all'). You don't need to delete the id's file since the same queries will be run. And in case you are wondering, it will only clean cache files in that directory, hence the need for a directory for every table.

The good. You don't even have to set a lifetime (they can exist forever) or autoclean for ur cache since u clean it yourself whenever you run an update, insert or delete.

The ugly. Any test, load or save will make two (or three, when we need to save a new id for a new query) requests to the file system.

I've used this and it works fine, using Zend_Cache_Core and Zend_Cache_Backend_File. I'm not using the full framework, but I use the Zend_Cache module so if you use the whole framework you may need to create an abstract model class that will be doing the creating of directories, id files, and caching for your model child classes (which will then extend it).

I've seen here that using md5 may be a solution to having to create an id's file for every table. I'll try it out and get back to you. I don't know how this would work with Apc.

Joey
  • 623
  • 1
  • 7
  • 7
  • I've tried md5 hashing and it's working. So in step 2 where you create an id's file all you have to do in its stead is this: //returns id for a given query function getCacheId($query) { return md5($query); } To make the md5 hash more robust you can salt it (maybe with the name of the table). //returns id for a given query function getCacheId($query, $table) { return md5($table . $query); } – Joey Jun 21 '10 at 03:06
  • if i use md5() to make id's from whatever ... how do i call the value of the $cache'd record later? my problem is that i am searching a couple of mysql db fields using a keyword value from a form field. when i link up my db search results with paginator, the $_POST data is lost when i go to the next page of results. won't the md5(whatever) also be destroyed on subsequent page loads? how can i call it on subsequent page loads? – b_dubb Jun 13 '11 at 17:01
0

What happens when your underlying data changes? Well, all applicable cache records should be scrapped. That's a mondo can of worms!

How about offloading this data caching to your RDBMS?

For example, MySQL Query Cache handles this for you, invalidating stale cache records as appropriate.

Derek Illchuk
  • 5,638
  • 1
  • 29
  • 29
  • The point of Zend_Cache is to remove load from the database, using a memcache or APC backend. Simply retrieving data by key is much faster than waiting for locked tables or relatively complex queries to complete. This does of course mean that more time is spent in developing your application, as you have to purge the cache when data is changed. This is the balance! Overall, there are big gains to be made - this is the reason why top websites cache data! – David Snabel-Caunt Dec 17 '09 at 00:00
  • 1
    OK, but which cache IDs would you clear with your serialize(func_get_args()) when some piece of data changes? As is, there's no way to know. So, either improve your method, or use the caching on the database side. We're arguing but neither of us has given a usable answer! – Derek Illchuk Dec 17 '09 at 01:49
  • Zend_Cache supports tagging, so you can tag records and then remove them as appropriate. Alternatively you can use a short TTL for data. What I'm trying to say is that there are different ways to cache things in different circumstances. Caching is VERY application specific. You raise a very valid point about being able to remove stale records! The query cache can be used in addition to this strategy. – David Snabel-Caunt Dec 17 '09 at 20:17
  • i'd love to see some code please. i have zend_cache 'working' on my app but since i'm using a static name to call the cached data i keep retrieving the same initial search. how do i make a md5() value persist over various page loads (using paginator here)? pass it in the URI? – b_dubb Jun 14 '11 at 13:53