Although CubeCart V4 is no longer an available product or is even supported by the CubeCart development team (Havenswift Hosting will still provide support for all clients that have one of our E-Commerce Shared Hosting packages !) there are a huge number of websites that for a variety of reasons are still running this version and will continue to do so for a long time to come. As CubeCart uses MySQL quite heavily it is very important that you choose a hosting company that :
Needless to say, Havenswift Hosting do this and a whole lot more for our E-Commerce Shared Hosting clients !
As far as changes that you as a store owner can make to your website, here is a list of some of most common ones that will have the greatest effect on your website
In the “General Settings” section of the CubeCart Administration panel you will find an option to “Use SQL Query Caching (Recommended!)” – this should be set to YES by default but we have often found this set to NO on sites. Enabling this option results in far fewer queries being made against the database, as once a query has been executed the results are stored in a cached file. These cached results can be accessed much faster than re-doing the queries again, which makes any page that needs those results, load much faster not just for that visitor but for every site visitor.
Many store owners decide that they don’t want this functionality on their website and simply remove the {RANDOM_PROD} tag from the styleTemplates/global/index.tpl file for their chosen skin. While this stops it from being displayed, the underlying query is still run for each and every page that is visited and if you say 1500 visitors per day who each click through 20 pages, this alone results in 30,000 extra queries per day being needlessly run.
To stop this query being run you need to also make the following code change so that the PHP code that runs the query which is found in includes/boxes/randomProd.inc.php is not included. We can do this as follows:
Open: includes/global/index.inc.php
Find: around lines 57-58
require_once"includes".CC_DS."boxes".CC_DS."randomProd.inc.php";
$body->assign("RANDOM_PROD",$box_content);Change To:
//require_once"includes".CC_DS."boxes".CC_DS."randomProd.inc.php";
//$body->assign("RANDOM_PROD",$box_content);Open: includes/global/cart.inc.php
Find: around lines 99-100
require_once"includes".CC_DS."boxes".CC_DS."randomProd.inc.php";
$body->assign("RANDOM_PROD",$box_content);Change To:
//require_once"includes".CC_DS."boxes".CC_DS."randomProd.inc.php";
//$body->assign("RANDOM_PROD",$box_content);
Another common box that many users remove from their skin is {POPULAR_PRODUCTS} and in the same way as for the {RANDOM_PROD} example above, simply removing this tag from the styleTemplates/global/index.tpl file for your skin can allow an unnecessary query to be run for every page view. So to correctly remove this, you also need to make the following code change
Open: includes/global/index.inc.php
Find: around lines 72-73
require_once"includes".CC_DS."boxes".CC_DS."popularProducts.inc.php";
$body->assign("POPULAR_PRODUCTS",$box_content);Change To:
//require_once"includes".CC_DS."boxes".CC_DS."popularProducts.inc.php";
//$body->assign("POPULAR_PRODUCTS",$box_content);Open: includes/global/cart.inc.php
Find: around lines 108-109
require_once"includes".CC_DS."boxes".CC_DS."popularProducts.inc.php";
$body->assign("POPULAR_PRODUCTS",$box_content);Change To:
//require_once"includes".CC_DS."boxes".CC_DS."popularProducts.inc.php";
//$body->assign("POPULAR_PRODUCTS",$box_content);
If you do display the Popular Products box on your site then within the Admin General Settings section there is a choice of what data is used to display the “Source for popular products data:” – this can either be “Number of Sales” or “Number of Views” If you choose “Number of Sales” to determine how popular a product is, then this query is already cached but if you choose “Number of Views” then this query is not cached which again means that each page view within your store runs this complex query !
Open: includes/boxes/popularProducts.inc.php
Find: around line 46
$popularProds = $db->select("SELECT I.name, I.productId FROM ".$glob['dbprefix']."CubeCart_inventory AS I, ".$glob['dbprefix']."CubeCart_category AS C WHERE C.cat_id = I.cat_id AND I.cat_id > 0 AND I.disabled = '0' AND (C.cat_desc != '##HIDDEN##' OR C.cat_desc IS NULL) ORDER BY I.popularity DESC",$config['noPopularBoxItems']);
Change To:
if (!$cache->cacheStatus) {
$popularProds = $db->select("SELECT I.name, I.productId FROM ".$glob['dbprefix']."CubeCart_inventory AS I, ".$glob['dbprefix']."CubeCart_category AS C WHERE C.cat_id = I.cat_id AND I.disabled = '0' AND (C.cat_desc != '##HIDDEN##' OR C.cat_desc IS NULL) ORDER BY I.popularity DESC",$config['noPopularBoxItems']);
$cache->writeCache($popularProds);
}
## $popularProds = $db->select("SELECT I.name, I.productId FROM ".$glob['dbprefix']."CubeCart_inventory AS I, ".$glob['dbprefix']."CubeCart_category AS C WHERE C.cat_id = I.cat_id AND I.cat_id > 0 AND I.disabled = '0' AND (C.cat_desc != '##HIDDEN##' OR C.cat_desc IS NULL) ORDER BY I.popularity DESC",$config['noPopularBoxItems']);
Making this change means that both types of queries are now cached and that the list of Popular products will not be 100% accurate (it is accurate to the last time that an admin user cleared cache so this should now be done every couple of weeks) but will again significantly reduce the number of queries being done
For stores with a large number of orders, the way this query is written often results in a massive overhead and seriously degraded performance. There are two options to solve this problem which are to
This is a complex area and there is not one simple solution that applies to all stores – much depends on the sizes of specific tables especially the inventory, category and order tables.
An index on a table acts like a pointer to the table rows, allowing a query to quickly determine which rows match a condition in the WHERE clause of a SELECT statement. When doing a query without an index, MySQL must begin with the first row and then read through the entire table to find the relevant rows and the larger the table, the more time this takes. If the table has an index for the columns used in the WHERE clause, then it can quickly determine the position in the middle of the data file to start retrieving matching records without having to look at all the data. According to the MySQL documentation “If a table has 1,000 rows, this is at least 100 times faster than reading sequentially.” There are a huge number of queries in CubeCart where the WHERE clause uses columns that are not indexed but it isnt always just a simple case of adding an index to any column that isnt already indexed !
One fairly simple example is that there a many queries that have a WHERE condition cat_id > 0 which immediately causes a table scan through every record of the inventory table. This is really bad for stores with tens or hundreds of thousands of products but what is worse is that the value in this column should never equal 0 ! The only place this can ever be set to zero is if the Import Catalogue routine is used and then the products are not assigned to a category.
There Are 2 Comments
Micky Harris on 22 Apr, 2014
Very useful info thanks.
I’ve implemented the removal of call to queries that are not required and the site does seem even quicker than usual!
However, the Popular and Random product file includes to comment out are in /includes/global/cart.inc.php and not includes/content/index.inc.php (in CC 4.4.5) as stated.
Cheers
Havenswift Hosting on 22 Apr, 2014
Hi Micky
Thanks for pointing out the filename path error in our original version although the files that need amending for both the Popular Products and the Random Product display are includes/global/index.inc.php AND includes/global/cart.inc.php and we have updated the article above to reflect the correct filenames and line numbers (as of the last release of V4 available which was 4.4.7)