Home › Toolset Professional Support › [Resolved] Need help optimizing load time with high number of view queries…
This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.
Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
---|---|---|---|---|---|---|
9:00 – 13:00 | 9:00 – 13:00 | 9:00 – 13:00 | 9:00 – 13:00 | - | - | 9:00 – 13:00 |
14:00 – 18:00 | 14:00 – 18:00 | 14:00 – 18:00 | 14:00 – 18:00 | - | - | 14:00 – 18:00 |
Supporter timezone: Africa/Casablanca (GMT+01:00)
Tagged: Views, Views plugin
This topic contains 5 replies, has 2 voices.
Last updated by shawnW-3 3 years, 6 months ago.
Assisted by: Jamal.
Tell us what you are trying to do?
I have a pretty complicated system of nested views designed to serve model information for models related to a series.
I'll do my best to break it down...
There's a spec table for every model type (taxonomy) showing the custom field data for each model (post type - child) related to the series (post type - parent) page in which they sit. This limits the models that show up on each table, while still giving us specs for every model related to the series
example:
SeriesTango (post page)
Model Type A will return a spec table with info for Modelx10 and Modelx12
Model Type B will return a spec table with info for Modelb1, Modelb2, Modelb3, Modelb4
Model Type C will return a spec table with info for Modelw6, Modelw8, Modelw10
...and so on...
For each model in the table there are approximately 100 possible rows. In other words, 100 queries through 100 views nested in a table view. When a view query produces a result, the view outputs a row to the table. The row is a container for the loop which produces one cell containing the spec for each model iteration.
When there are just one or two Model Type for a Series, there are one or two specs tables, and thus approximately 100 or 200 queries running on a Series Post. Not great, but not terrible.
But I do have one Series in particular with Six Model Types, creating six tables, with each table containing a wide range of specs for 1 - 6 models (19 models in total across all six tables). At least 600 queries are firing off on load, which drags the load time way down.
One idea I had on how to get the speed back up...
An important thing to note is that I currently use a Switcher - hidden link - for each Model Type / Table. So if we could defer the query for non-active containers until the associated tab is clicked, that would bring the initial load from 600 queries back down to 100 (for the active tab)... This would work like pagination, but I can't think of how to combine the existing pagination tools with something as elegant as the switcher.
But honestly, I'm open to anything. It'd be nice if there was a way to ignore the views that produce rows in each table based on the model type, but I figure wrapping each view a conditional would add another type of query, and adding model type to the query filter for each view doesn't prevent the view from running it's query on page load.
Is there any documentation that you are following?
I read other posts on the forum about having too many nested views and how taxing they can be, but I didn't see any solutions.
Is there a similar example that we can see?
Not that I know of.
What is the link to your site?
I'd be happy to share that information privately, but I will need the Toolset Supporter's IP address to whitelist.
Hello and thank you for contacting the Toolset support.
Honestly, I still do not see the custom post types, custom taxonomies, and relationships involved in your system. Can you provide more details? I'd like to login into your admin area to see this closer, but I am afraid my IP address will change over time. I need to check with our system team for a VPN connection in order to guarantee one IP. We can check that later.
When a view is part of a page it will be evaluated on page load. This means, that we can't easily load a view over AJAX. But, we still can. For example, if the view sits in a different URL, you can integrate the Switcher component to trigger an AJAX call to this page, get the results, extract the view from it, and add it to the current page.
hidden link
You can activate caching for the views, this way Toolset will not regenerate the views each time, but the Toolset validation cache gets invalidated whenever a post is added/updated/deleted. Depending on how often your data changes this can be a good solution.
You may also create your own shortcodes that will generate and cache the views. This way, you have more control over the cache invalidation, you will decide when a view's cache needs to be purged.
- https://developer.wordpress.org/apis/handbook/transients/
- https://developer.wordpress.org/reference/functions/do_shortcode/
Something like:
add_shortcode('my_nested_view_1', function(){ if ( you_logic_to_decide_if_the_cache_is_invalid() ) { $cache = your_logic_to_get_the_cached_view(); return $cache; } else { $result = do_shortcode('[wpv-view name="the-view"]'); your_logic_to_set_the_cached_view($result); return $result; } });
Implementing different caching layers on your server will definitely improve the rendering time of the page. There are multiple caches that may be implemented:
- On WordPress layer using a caching plugin https://wordpress.org/plugins/tags/cache/
- On server level hidden link
- Browser caching, even if it is not involved in the page/view generation, but it will definitely reduce loading time hidden link
I hope this gives some useful information. Let me know if you have further questions.
We'll take a closer look at cache options, but a large number of our users will be first time viewers. Am I wrong in thinking that the caching options listed won't significantly benefit someone arriving on the page for the first time?
When a view is part of a page it will be evaluated on page load. This means, that we can't easily load a view over AJAX. But, we still can. For example, if the view sits in a different URL, you can integrate the Switcher component to trigger an AJAX call to this page, get the results, extract the view from it, and add it to the current page.
I would definitely need some more advice to making this approach work.
Using very simple ajax I rendered the shortcode, which came through as plaintext. I tried a few different things... made a php file using "Custom Code" feature in settings, and tried both do_shortcode and render_view ... neither produced a result. do_shortcode had an error detected, and I think it may have to do with the attributes within. render_view didn't show an error in the Custom Code panel, but it didn't seem to work.
Bit frustrating, I had hoped that ajax would be a simple solution. Please let me know if you have any tips.
but I am afraid my IP address will change over time
We haven't had any issues with other Toolset supporters. The odds of the IP changing within a two day window are probably around one in forty-five, or less.
The cache is always implemented at different layers, server-level caching, application caching and then browser caching. The browser caching only has benefits in subsequent visits to the page, the first visit does not benefit from it. Check this article hidden link
I would definitely need some more advice to making this approach work.
Check this article hidden link
Implementing your own caching using shortcodes is not that simple. It is a complex task, and if you are not comfortable with programming, you should hire a developer. Check the list of our partners here https://toolset.com/contractors/
If you think that do_shortcode and render_view do not return the extepected results, please let me know an example to reproduce in my tests and if I spot a bug, I'll escalate it to our developers.
Consider using wpv_do_shortcode which is similar to do_shortcode with some Toolset specific additions, such as rendering nested shortcodes and conditional shortcodes.
If you want me to check the view on your admin area, I am setting your next reply to be private to let you share credentials safely. ** Make a database backup before sharing credentials. **
My current IP is 160.176.145.7
I was originally using $.ajax, but what you sent looks cleaner. Unfortunately I'm still not getting any positive results.
Below is one way I tried using the tutorial example and custom code created in the settings...
The alert shows a 404 error. I tried changing it to a function which would output it as a shortcode, but that didn't work for the same reason the .txt method wasn't working. On that note, I can access files directly without getting a 404 error, but as I've said they don't render properly. Please take a look and if you see anything, please let me know. If after reviewing this, you still don't see the issue, I can give you access to the site.
Container View where the nested views are to Render- Taxonomy: Model Types ... Taxonomy is set by the current post
[wpv-layout-start] [wpv-items-found] <!-- wpv-loop-start --> <ul class="uk-switcher type-container"> <wpv-loop> [wpv-post-body view_template="loop-item-in-series-child-product-type-spec-separator-containers"] </wpv-loop> </ul> <!-- wpv-loop-end --> [/wpv-items-found] [wpv-no-items-found] <strong>[wpml-string context="wpv-views"]No items found[/wpml-string]</strong> [/wpv-no-items-found] [wpv-layout-end]
<li class="prod-type-switcher-container [wpv-taxonomy-slug] uk-padding uk-padding-remove-top uk-padding-remove-left"> </li>
JS in Header
jQuery(document).ready(function($){ $('.prod-type-switcher-click').click(function(){ var modeltypetitle = $(this).attr('tabname'); $('.prod-type-switcher-container.' + modeltypetitle).load("/home/ --- SITE NAME --- / --- DOMAIN --- /wp-content/toolset-customizations/modeltypecontainer.php", function(responseTxt, statusTxt, jqXHR){ if(statusTxt == "success"){ alert("New content loaded successfully!"); } if(statusTxt == "error"){ alert("Error: " + jqXHR.status + " " + jqXHR.statusText); } }); }); });
modeltypecontainer - Status: Active, Run: Always, Context: Everywhere
<?php /** * New custom code snippet (replace this with snippet description). */ toolset_snippet_security_check() or die( 'Direct access is not allowed' ); // Put the code of your snippet below this comment. $containerresult = wpv_do_shortcode('[wpv-view name="universal-model-specs-tax-parent-model-type-desktop-only" tabname="[wpv-taxonomy-slug]"]' . '[wpv-view name="universal-model-specs-tax-parent-set-type-desktop-only" tabname="[wpv-taxonomy-slug]"]'); return $containerresult;
VIEW "universal-model-specs-tax-parent-model-type-desktop-only" (the second of the two nested views is very similar).
Post types: Models ...
Select posts in a Series Models relationship that are a related to the current post in the loop.
Model Types set by the parent Taxonomy View
Select items with field:
Is this product Global Page Only? is a number equal to URL_PARAM(global)
AND
Availability Status is a string different from URL_PARAM(status)
AND
Is this product only available in a set? is a number different from 1
[wpv-layout-start] [wpv-items-found] <!-- wpv-loop-start --> <wpv-loop> [wpv-post-body view_template="loop-item-in-universal-model-specs-tax-parent-model-type-desktop-only"] </wpv-loop> <!-- wpv-loop-end --> <div class="uk-align-center"> <table class="uk-table uk-table-middle uk-table-hover" tablename="striped"> <thead> [wpv-view name="table-spec-model-number" wpvmodeltype="[wpv-attribute name="modeltype"]"] </thead> <tbody> [wpv-view name="table-spec-driver-size-primary-inches"] [wpv-view name="table-spec-driver-size-primary-mm"] [wpv-view name="table-spec-driver-size-secondary-inches"] [wpv-view name="table-spec-driver-size-secondary-mm"] [wpv-view name="table-spec-watts-rms"] [wpv-view name="table-spec-peak-power"] [wpv-view name="table-spec-vcd-primary-inches"] [wpv-view name="table-spec-vcd-primary-mm"] [wpv-view name="table-spec-vcd-secondary-inches"] [wpv-view name="table-spec-vcd-secondary-mm"] [wpv-view name="table-spec-voice-coil-impedance"] [wpv-view name="table-spec-frequency-response-hz"] [wpv-view name="table-spec-dbspl"] [wpv-view name="table-spec-piston-diameter-inches"] [wpv-view name="table-spec-piston-diameter-mm"] [wpv-view name="table-spec-fs"] [wpv-view name="table-spec-qms"] [wpv-view name="table-spec-qes"] [wpv-view name="table-spec-qts"] [wpv-view name="table-spec-vas-liters"] [wpv-view name="table-spec-xmech-inches"] [wpv-view name="table-spec-xmech-mm"] [wpv-view name="table-spec-xmax-inches"] [wpv-view name="table-spec-xmax-mm"] [wpv-view name="table-spec-displacement-cubic-feet"] [wpv-view name="table-spec-displacement-liters"] [wpv-view name="table-spec-sealed-enclosure-cubic-feet"] [wpv-view name="table-spec-sealed-enclosure-liters"] [wpv-view name="table-spec-ported-enclosure-cubic-feet"] [wpv-view name="table-spec-ported-enclosure-liters"] [wpv-view name="table-spec-frame-od-inches"] [wpv-view name="table-spec-frame-od-mm"] [wpv-view name="table-spec-frame-od-gasket-inches"] [wpv-view name="table-spec-frame-od-gasket-mm"] [wpv-view name="table-spec-motor-diameter-inches"] [wpv-view name="table-spec-motor-diameter-mm"] [wpv-view name="table-spec-motor-depth-inches"] [wpv-view name="table-spec-motor-depth-mm"] [wpv-view name="table-spec-mounting-diameter-inches"] [wpv-view name="table-spec-mounting-diameter-mm"] [wpv-view name="table-spec-mounting-depth-inches"] [wpv-view name="table-spec-mounting-depth-mm"] [wpv-view name="table-spec-operating-voltage"] [wpv-view name="table-spec-input-channels"] [wpv-view name="table-spec-output-channels"] [wpv-view name="table-spec-test-voltage"] [wpv-view name="table-spec-continuous-wattage-at-4-ohm"] [wpv-view name="table-spec-continuous-wattage-at-2-ohm"] [wpv-view name="table-spec-continuous-wattage-at-1-ohm"] [wpv-view name="table-spec-dynamic-wattage"] [wpv-view name="table-spec-pass-thru-output"] [wpv-view name="table-spec-remote-sub-control-option"] [wpv-view name="table-spec-wire-gauge-in"] [wpv-view name="table-spec-wire-gauge-out"] [wpv-view name="table-spec-damping-factor"] [wpv-view name="table-spec-max-current-draw-amps"] [wpv-view name="table-spec-rca-input-voltage-sensitivity"] [wpv-view name="table-spec-high-level-input-voltage-sensitivity"] [wpv-view name="table-spec-rca-input-s-n"] [wpv-view name="table-spec-high-level-input-s-n"] [wpv-view name="table-spec-thd"] [wpv-view name="table-spec-low-pass-filter"] [wpv-view name="table-spec-sub-sonic-filter"] [wpv-view name="table-spec-bass-boost"] [wpv-view name="table-spec-wattage"] [wpv-view name="table-spec-rca-input-impedance"] [wpv-view name="table-spec-high-level-input-impedance"] [wpv-view name="table-spec-rca-output-impedance"] [wpv-view name="table-spec-rca-output-voltage"] [wpv-view name="table-spec-rca-remote-out-current"] [wpv-view name="table-spec-gauge"] [wpv-view name="table-spec-wire-type"] [wpv-view name="table-spec-spool-length-feet"] [wpv-view name="table-spec-spool-length-meters"] [wpv-view name="table-spec-strand-count"] [wpv-view name="table-spec-rated-input-power"] [wpv-view name="table-spec-max-input-power"] [wpv-view name="table-spec-right-left-balance"] [wpv-view name="table-spec-cable"] [wpv-view name="table-spec-plug"] [wpv-view name="table-spec-audio-input"] [wpv-view name="table-spec-battery"] [wpv-view name="table-spec-playtime"] [wpv-view name="table-spec-driver"] [wpv-view name="table-spec-can-front-od-inches"] [wpv-view name="table-spec-can-front-od-mm"] [wpv-view name="table-spec-can-depth-inches"] [wpv-view name="table-spec-can-depth-mm"] [wpv-view name="table-spec-port-length-inches"] [wpv-view name="table-spec-port-length-mm"] [wpv-view name="table-spec-port-diameter-inches"] [wpv-view name="table-spec-port-diameter-mm"] <!-- Universal Product Specs - Start --> [wpv-view name="table-spec-dimensions-inches"] [wpv-view name="table-spec-dimensions-mm"] [wpv-view name="table-spec-ship-weight-lbs"] [wpv-view name="table-spec-ship-weight-kg"] [wpv-view name="table-spec-price-usd"] <!-- Universal Product Specs - End --> </tbody> </table> </div> [/wpv-items-found] [wpv-no-items-found]<span class="emptynavtabmodeltoken" tabname="[wpv-attribute name='tabname']"></span>[/wpv-no-items-found] [wpv-layout-end]
And for deeper understanding, here is how a Table Spec View looks...
Post types: Models ...
Select posts in Any relationship that are related to the Post where this View is shown.
Model Types set by the parent Taxonomy View
Select items with field:
Availability Status is a string different from URL_PARAM(status)
AND
Is this product Global Page Only? is a number equal to URL_PARAM(global)
AND
Does this product appear on the Global Page? is a number equal to URL_PARAM(place)
[wpv-layout-start] [wpv-items-found] <!-- wpv-loop-start --> <tr class="ddspecnacheckrow"> <td><strong>Xmax (In):</strong></td> <wpv-loop> [wpv-post-body view_template="loop-item-in-table-spec-xmax-inches"] </wpv-loop> </tr> <!-- wpv-loop-end --> [/wpv-items-found] [wpv-no-items-found] [wpml-string context="wpv-views"][/wpml-string] [/wpv-no-items-found] [wpv-layout-end]
<td class="ddspecnacheckcell" data-prod-src="[wpv-post-title]" data-spec-label="Xmax - Inches" title="[wpv-post-title] - Xmax - Inches">[types field="xmax-in"][/types] [wpv-conditional if="( $(wpcf-xmax-in) eq '' )"] <span class="ddspecnatrue">N/A</span> [/wpv-conditional] </td>
I ended up implementing a few of those caching options and they improved the speed enough that the ajax call is no longer necessary. My issue is resolved now. Thank you!