Best practices for using the transients API

I’ve recently come across the Transients API in WordPress in hopes of improving the performance of the plugin that I’m trying to write.

Basically the plugin is storing product details from the amazon product advertising API in the database. The product details are stored using the json encoded representation of the array.

Read More

Now I’m trying to use the transients API so that whenever the admin purges the database records it also updates using the transients API.

What I’m currently doing is storing the json encoded value using the set_transient method. Something like this:

$data = array(
 '123' => "{'title' : '', 'price' : '', 'brand' : ''}"
 '456' => ...
);

$value = json_encode($data);
set_transient('amazon_items', $value, 60 * 60);

And then I get it from there using get_transient

$asin = '123';
$data = json_decode(get_transient('amazon_items'), true);
print_r($data[$asin]);

Is this ok or should I just store it in an array form so I can just directly access it without using json_decode? Is my use case acceptable or is it overkill? Can I still improve this one? Is there a specific limit to how much data I can store using the transients API? In this particular use case I’m expecting it to be more than 50Mb of data.

Related posts

2 comments

  1. Is this ok or should I just store it in an array form so I can just
    directly access it without using json_decode?

    In your case store it directly means store it serialized. Because $data is an array and cannot be stored as is, but converted to a string.

    Even if you access it directly like:

    $data = get_transient('amazon_items');
    print_r( $data[0] );
    

    the get_transient function unserialize the value behind the scenes (just like the set_transient serialize behind the scenes), using the WP maybe_unserialze function that use the serialize php function.

    So using json_encode/json_decode or using the standard php-serialize method there are some differences, but performance are almost the same. People who have done tests say json_encode is a little bit faster.

    The method you have to choose depends on what you have to do with data: if you plan to manipulate it with js (or even with other languages than php) the right choose is most probably json.

    If you have to serialize php object, mantaining the original class you have to use php serialization:

    $a = new MyClass;
    $b = json_encode($a);
    $c = json_decode($b);
    $test = is_a($c, 'MyClass'); // false
    
    $a = new MyClass;
    $b = serialize($a);
    $c = unserialize($b);
    $test = is_a($c, 'MyClass'); // true
    

    Is there a specific limit to how much data I can store using the
    transients API?

    Transient API use {$wpdb->prefix}_options to save data. In this table the option_value column where data are stored is a longtext column that can theoretically contain 4Gb of data. Even if real space is less, 50Mb should not brings any problems (of course if your db space in server is big enough).

    Side Notes

    1. When work with serialized data (json or php make no difference) you should be aware that running any type of SQL query that makes use of them is almost impossible. “Almost” is there for some LIKE %..% queries…
    2. The process of serialization / deserialization is a bit expensive, especially for big data. So it can be (and actually is) useful, but try to keep this type of calls less frequent as possible, and if possible once a value is retrieved try to cache it in some way
  2. I would not be storing 50+ meg as a transient. I would look into storing it in the filesystem somehow, or creating my own specific db table to store the data.

    Consider that if you’re storing the transient in the database, then every time you pull it, that’s 50 meg of data that has to be sent from the DB to the webserver for processing. And that’s 50 meg of memory that PHP has to allocate to hold it. And so forth. Are you using that entire 50 meg every time? No? Then it’s wasteful and silly.

    Break apart your data. Don’t treat it as one-big-blob, instead store it in its own table, or as its own post type, or whatever. Use keys to access it, and only access the pieces you need. You will see speed benefits and have a better codebase to work with in this manner.

Comments are closed.