<p>Disclaimer: While <a href="https://docs.craftcms.com/v3/dev/eager-loading-elements.html" rel="nofollow noreferrer">eager-loading</a> will almost always bring down the total number of queries executed, it's important to note that having less queries won't <em>always</em> equal better performance. When optimising a page with eager-loading, you should take care to observe the actual <em>time</em> Craft spends on database queries – which is the metric that matters.</p>

<p>For Craft 3, you should enable the <a href="https://craftcms.com/features/debug-toolbar" rel="nofollow noreferrer">Debug Toolbar</a>, which will tell you exactly how many milliseconds Craft is using for database queries. Eager loading is not a silver bullet, and you should note the time spent on database queries with and without eager loading, to determine if it's actually increasing performance or not. <em>You can enable the debug toolbar from your Craft user's profile page inside the Control Panel.</em></p>

<p><em>For Craft 2, you'll need to enable <a href="https://craftcms.com/support/dev-mode" rel="nofollow noreferrer"><code>devMode</code></a>, crack open your browser's dev tools console and expand the *Profiling Summary Report*. Unfortunately, AFAIK there's no record of the time spent on queries specifically, but you can gauge it by looking at the <code>Time</code> property (which will report the total time Craft spent resolving the request, including database queries). Obviously, the lower this number is, the better.</em></p>

<p>Furthermore, before worrying about eager loading, you should make sure that your template is properly optimised without it. The most important thing is to make sure that you're not doing multiple, redundant queries.</p>

<p>In the code example above, you're first executing two queries on the <code>entry.imageGallery()</code> field outside the <code>{% for %}</code> loop, and then 1 additional query per image inside the <code>{% for %}</code> loop. In other words, if you added 100 images to the <code>galleryImages</code> field, you'd execute a total of 102 queries – which is totally unnecessary.</p>

<p>By caching the array of Assets returned by <code>.all()</code> to a variable, you can get away with a single query:</p>

<pre><code>{# Get all images in the field #}
{% set galleryImages = entry.galleryImages.all() %}

{# Set the `titleImage` to the first image #}
{% set titleImage = galleryImages[0] ?? null %}

{% if titleImage %}
    ...
{% endif %}

{{ entry.bodyText }}

{# Use the |slice filter to remove the first image – i.e. the title image – from the Assets array, and then print the rest of the images #}
{% set galleryImages = galleryImages|slice(1) %}

{% if galleryImages|length %}
    {% for image in galleryImages %}
        ...
    {% endfor %}
{% endif %}
</code></pre>

<p><em>Note the use of the <a href="https://twig.symfony.com/doc/2.x/filters/slice.html" rel="nofollow noreferrer"><code>|slice</code></a> filter – this is used to remove the first index (i.e. the first image) from the array, after caching it to a variable <code>titleImage</code>. Don't worry, the <code>|slice</code> operation won't throw an error, even if the <code>galleryImages</code> array is empty.</em></p>

<p>With the above optimisation, your X number of queries have been reduced to a single query – and at that point, you probably wouldn't see any performance improvements by adding eager loading.</p>

<p>But, if you wanted to try it – here's how it could be done (this would replace the first line in the above example):</p>

<pre><code>{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages']
) %}
</code></pre>

<p>The above statement should go at the very top of your template – and if you do this, make sure to remove the reference to <code>.all()</code> in the first line of the first example (by eager loading the Assets field, the <code>entry.galleryImages</code> property is already an array and hence has no <code>all()</code> method).</p>

<p>Again, the above is probably not useful if you do the optimisations to bring down your query count to 1 – but, it could be useful if you had multiple relational fields you wanted to query, i.e.</p>

<pre><code>{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages', 'entriesField', 'categoryField']
) %}
</code></pre>

<p>For more info on eager loading, check out <a href="https://nystudio107.com/blog/speed-up-your-craft-cms-templates-with-eager-loading" rel="nofollow noreferrer">this excellent article</a>.</p>

CC BY-SA 4.0
2018-08-14T14:09:24.720Z
So you actually can do it like this in Craft 3 (rather than reloading the entry): https://twitter.com/nystudio107/status/1023803776279498752
andrew.welch
CC BY-SA 4.0
2018-08-14T15:45:18.003Z
@andrew.welch Aha, nice one! Didn't know about that – I'll edit the answer. Thanks!
Mats Mikkel Rummelhoff
CC BY-SA 4.0
2018-08-14T17:15:08.170Z
Helpful explanation Mats.
I have already been using the Debug Toolbar.
What about the transforms, can/how/should they be pre-loaded?
Paul Frost
CC BY-SA 4.0
2018-08-14T20:35:45.473Z
Eager Beaver really is just a shorthand way to do exactly that @MatsMikkelRummelhoff -- while there is no great need for the plugin on Craft 3, it makes the syntax a little cleaner, and ends up calling the same Craft core routine. The primary reason I ported it to Craft 3 is so people who used it on Craft 2.x could upgrade their sites without changing their template code.
andrew.welch
CC BY-SA 4.0
2018-08-14T22:49:30.230Z
@MatsMikkelRummelhoff is a machine.
Brad Bell
CC BY-SA 4.0
2018-08-15T05:04:46.833Z
@andrew.welch Yeah, got it! It was even mentioned in your article, but I missed it the first time around :P Cool stuff.
Mats Mikkel Rummelhoff
CC BY-SA 4.0
2018-08-14T11:12:33.857Z
2018-08-14T15:52:43.187Z
2018-08-14T15:52:43.187Z
Mats Mikkel Rummelhoff
<p>This is a single entry page. I have an assets field of imageGallery which allows multiple images to be uploaded but it could also be empty. I want to use the first image at the top of the page (if one exists) then show the rest of the images (if there is more than one) excluding the first one after the bodyText field. I'm also loading a transform named 'gallery' if the original image is larger than the transform. This is the code I have now (simplified for clarity):</p>

<pre><code>{% set titleImage = entry.imageGallery[0] ?? null %}

{% if titleImage|length %}
    {% if titleImage.getWidth()&gt;titleImage.getWidth('gallery') %}
        &lt;img src="{{ titleImage.url('gallery') }}"
    {% else %}
        &lt;img src="{{ titleImage.url }}"
    {% endif %}
{% endif %}

{{ entry.bodyText }}

{% if entry.imageGallery.count() &gt; 1 %}
    {% for image in entry.imageGallery.offset(1).all() %}
        {% if image.getWidth()&gt;image.getWidth('gallery') %}
            &lt;img src="{{ image.url('gallery') }}"
        {% else %}
            &lt;img src="{{ image.url }}"
        {% endif %}
    {% endfor %}
{% endif %}
</code></pre>

<p>How could this be impoved on for faster loading?</p>

CC BY-SA 4.0
2018-08-14T13:47:40.503Z
Just as an additional note besides @mats great answer. The `count()` function executes the query and counts the results, `imageGallery[0]` is a deprecated way to execute the query and you'll finally execute it a 3rd time with `.offset(1).all()`. So you execute 2 useless queries that could be avoided
Robin Schambach
<performance><eager-loading>
How to speed up a single entry page with Eager Loading
# How to speed up a single entry page with Eager Loading

(Asked by: username_0 on 2018-08-14)

This is a single entry page. I have an assets field of imageGallery which allows multiple images to be uploaded but it could also be empty. I want to use the first image at the top of the page (if one exists) then show the rest of the images (if there is more than one) excluding the first one after the bodyText field. I'm also loading a transform named 'gallery' if the original image is larger than the transform. This is the code I have now (simplified for clarity):
{% set titleImage = entry.imageGallery[0] ?? null %}

{% if titleImage|length %}
    {% if titleImage.getWidth()>titleImage.getWidth('gallery') %}
         1 %}
    {% for image in entry.imageGallery.offset(1).all() %}
        {% if image.getWidth()>image.getWidth('gallery') %}
            
How could this be impoved on for faster loading?

**Tags:** performance, eager-loading
> **Comments:**
> **username_1**: Just as an additional note besides @mats great answer. The `count()` function executes the query and counts the results, `imageGallery[0]` is a deprecated way to execute the query and you'll finally execute it a 3rd time with `.offset(1).all()`. So you execute 2 useless queries that could be avoided  

---

## 1 answers

### Answer by username_2 on 2018-08-14. Score: 4 | Accepted answer

Disclaimer: While eager-loading will almost always bring down the total number of queries executed, it's important to note that having less queries won't always equal better performance. When optimising a page with eager-loading, you should take care to observe the actual time Craft spends on database queries – which is the metric that matters.
For Craft 3, you should enable the Debug Toolbar, which will tell you exactly how many milliseconds Craft is using for database queries. Eager loading is not a silver bullet, and you should note the time spent on database queries with and without eager loading, to determine if it's actually increasing performance or not. You can enable the debug toolbar from your Craft user's profile page inside the Control Panel.
For Craft 2, you'll need to enable devMode, crack open your browser's dev tools console and expand the *Profiling Summary Report*. Unfortunately, AFAIK there's no record of the time spent on queries specifically, but you can gauge it by looking at the Time property (which will report the total time Craft spent resolving the request, including database queries). Obviously, the lower this number is, the better.
Furthermore, before worrying about eager loading, you should make sure that your template is properly optimised without it. The most important thing is to make sure that you're not doing multiple, redundant queries.
In the code example above, you're first executing two queries on the entry.imageGallery() field outside the {% for %} loop, and then 1 additional query per image inside the {% for %} loop. In other words, if you added 100 images to the galleryImages field, you'd execute a total of 102 queries – which is totally unnecessary.
By caching the array of Assets returned by .all() to a variable, you can get away with a single query:
{# Get all images in the field #}
{% set galleryImages = entry.galleryImages.all() %}

{# Set the `titleImage` to the first image #}
{% set titleImage = galleryImages[0] ?? null %}

{% if titleImage %}
    ...
{% endif %}

{{ entry.bodyText }}

{# Use the |slice filter to remove the first image – i.e. the title image – from the Assets array, and then print the rest of the images #}
{% set galleryImages = galleryImages|slice(1) %}

{% if galleryImages|length %}
    {% for image in galleryImages %}
        ...
    {% endfor %}
{% endif %}

Note the use of the |slice filter – this is used to remove the first index (i.e. the first image) from the array, after caching it to a variable titleImage. Don't worry, the |slice operation won't throw an error, even if the galleryImages array is empty.
With the above optimisation, your X number of queries have been reduced to a single query – and at that point, you probably wouldn't see any performance improvements by adding eager loading.
But, if you wanted to try it – here's how it could be done (this would replace the first line in the above example):
{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages']
) %}

The above statement should go at the very top of your template – and if you do this, make sure to remove the reference to .all() in the first line of the first example (by eager loading the Assets field, the entry.galleryImages property is already an array and hence has no all() method).
Again, the above is probably not useful if you do the optimisations to bring down your query count to 1 – but, it could be useful if you had multiple relational fields you wanted to query, i.e.
{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages', 'entriesField', 'categoryField']
) %}

For more info on eager loading, check out this excellent article.

> **Comments:**
> **username_3**: So you actually can do it like this in Craft 3 (rather than reloading the entry): https://twitter.com/nystudio107/status/1023803776279498752  
> **username_2**: @andrew.welch Aha, nice one! Didn't know about that – I'll edit the answer. Thanks!  
> **username_0**: Helpful explanation Mats. I have already been using the Debug Toolbar. What about the transforms, can/how/should they be pre-loaded?  
> **username_3**: Eager Beaver really is just a shorthand way to do exactly that @MatsMikkelRummelhoff -- while there is no great need for the plugin on Craft 3, it makes the syntax a little cleaner, and ends up calling the same Craft core routine. The primary reason I ported it to Craft 3 is so people who used it on Craft 2.x could upgrade their sites without changing their template code.  
> **username_4**: @MatsMikkelRummelhoff is a machine.  
> **username_2**: @andrew.welch Yeah, got it! It was even mentioned in your article, but I missed it the first time around :P Cool stuff.  

---

