Improving Advanced Custom Fields Repeater performance

If you’ve ever used Advanced Custom Fields Repeater add-on with a large number of items, you must have noticed that it’s super ineffective when it comes to database queries – you can easily reach hundreds of queries with a couple of repeaters and lots of items. While WordPress in general is well optimized for a large number of small database queries, a huge number of them will still slow your site down.

Here’s what can easily happen when dealing with, for example, a large number of images on a single page:

acf_repeater_queries

 

While the actual time spent on database queries was fairly small, the overhead from PHP parsing all the data meant that it took >5 seconds for WP to actually render this page on a slowish shared hosting server. This is way too much.

Fortunately, there’s an easy workaround for this problem – cache (pre-load) all posts with a smaller number of queries.

A working example with image galleries

First, you’ll need to make sure the image field inside the Repeater returns image IDs and not objects or URLs – in order to return the object or URL, the repeater will already have to make multiple DB queries.

acf_repeater_img

The corresponding code would look like this:

<?php 
$rows = get_field('galleries');
foreach ($rows as $row):

    $image_id = $row['image'];
    $image = wp_get_attachment_image_src($image_id, 'your-custom-image-size'); ?>

    <img src="<?php echo $image[0]; ?>" width="<?php echo $image[1]; ?>" height="<?php echo $image[2]; ?>" />

<?php endforeach; ?>

Now, let’s add caching – this should go after line 1 in the previous example:

foreach ($rows as $row) {
    $ids[] = $row['image'];
}
$cache = get_posts(array('post_type' => 'attachment', 'numberposts' => -1, 'post__in' => $ids));

This code will store each image ID in the $ids array and make one single database query for getting all the images’ data. Since the results of the query are stored in WP’s internal cache, subsequent calls to wp_get_attachment_image_src() won’t have to make separate database queries.

 

This is the same page as above after I added caching – it reduced the number of queries by almost 10x.

acf_repeater_results

If you add W3 Total Cache on top of this, your page should end up loading pretty fast.

Thanks to @TripleM for the general idea.

Indrek Kõnnussaar

I'm a veteran Wordpress developer, context-driven tester, security enthusiast and the mastermind behind Codelight. I love building stuff that works and fixing stuff that doesn't.

Write me directly indrek@codelight.eu

4 Responses to “Improving Advanced Custom Fields Repeater performance”

  1. Jonathan

    This is very clever. In a quick test with just 4 images this technique has eliminated 6 database queries, so I imagine that on a large repeater the savings will be quite substantial. Good work!

    Reply
  2. John R.

    Hi Indrek,

    Thanks for writing this article. We use ACF for very large websites, and have been struggling with query efficiency. Quick question – what plugin did you use in your first screenshot to see the number of queries on the page and the execution time?

    Reply
    • Indrek Kõnnussaar

      Hey John. We used Debug Bar there. A more powerful alternative is Debug Objects (although it didn’t work properly some 4-5 months ago iirc).

      If you have difficulties with lots of queries, have you tried using a proper caching plugin? Obviously this doesn’t actually solve the query problem, but would allow you to bypass it for most of the time.

      Reply
  3. dariush

    hey. can you review this and put in your blog
    https://github.com/devlifeX/acf-getallobjects

    Reply

Leave a Reply

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×