Category Archive:

TruboImages ReleaseCandidate – volounteers needed.

5

I’ve created module that spreads images over given number of subdomains on store. It greatly speeds up page loading times, gives better performance score in Google Page Speed and Yahoo YSlow. I’m not completely sure, but it should also affect SEO due to not-so-recent Google decision to take into account page speed.

I think it is great way to speed up any Zen Cart store which contains lots of images.

Here’s simple overview of what the module does.
It changes all urls of images on Your store from:

http://www.mydomain.com/images/products/my_product.jpg

http://www.mydomain.com/images/products/my_product2.jpg

http://www.mydomain.com/images/products/my_product3.jpg

to

http://www.img1.mydomain.com/images/products/my_product.jpg

http://www.img2.mydomain.com/images/products

http://www.img3.mydomain.com/images/products/my_product.jpg/my_product.jpg

It’s done automatically, no manual mapping <imgX,subdomainY> is needed.

Unfortunately the module isn’t yet completely finished and I don’t have time to test it completely. I’m looking for volunteers for ‘Release Candidate’ quality installation. I’ll guide You with installation and provide support, or I may install the module myself.

Anyone interested in participating in tests please either PM on zen-cart.com or send me email via www.data-diggers.com. Please keep in mind that You must be able to create subdomains  for Your domain.

Regards,
Data-Digger.


Continue Reading

QueryCache v1.7 Beta for ZenCart 1.3.9h is available

8

Yes, finally! I’m sorry it took so long. You can download it from:

Query Cache v1.7-beta

Installation instructions are in .zip file. Currently the package is released as beta. Please report any bugs either via email or below in comments.

Changes:

  • Works with Zen Cart 1.3.9h
  • Few memory tweaks
  • Few bug fixes
Posted in: Performance, Query Cache

Continue Reading

Request to Query Cache users

2

I promised to release new, more memory efficient version of Query Cache soon  – unfortunately (or fortunately) it seems that PHP is quite good at managing memory and there’s not much to improve. Therefore version 1.7 of Query Cache will be delayed.

Request to Query Cache users:

If You use Query Cache and Your store is still slow and it’s not related to search script please contact me either on email, PM on Zen-Cart.com (data_digger) or by leaving comment. I’ll check Your site and try to make necessary changes in Query Cache v1.7 for You.

Posted in: Performance, Query Cache

Continue Reading

Speed up admin/orders.php page

1

There’s suboptimal query in admin/orders.php page which retrieves information about last orders. Unfortunately query is constructed in such way that MySQL scans whole orders, orders_products and orders_total table. As always it’s not a problem until orders table gets big ( for example 50 000 entries ). If You happen to have at least 10 000 orders ( I wish You that ;) ), You probably get impatient each time You request admin/orders.php page.

Good news is that there is quick fix. Just add index on (orders_id, class) on orders_total table to speed up the query. Here’s MySQL statement which does that for You:

ALTER TABLE orders_total ADD INDEX idx_oid_class(orders_id, class)

The query is still suboptimal, but at least its quite fast until orders table gets really big (500 000 orders? It’ll depend on Your server).


Continue Reading

Performance issues with Store Credit Module in admin area

0

Store Credit is great module, unfortunately it’s preety inefecient in some places. For example, on every page request of admin/store_credit.php whole customers table is read, and for each customer additional SELECT and UPDATE query is executed to calculate and update pending points, even if the customer does not have any pending points!

It’s not a big deal when You have up to 1000 customers, but when there are more then 100 000 customers page loads in 30 seconds (store_credit.php executes over 2 x customer count,  or in this example over 200 000 queries on each request).

To address that, change following code in admin/store_credit.php:

function store_pending_rewards() {
        global $db;

        $customers = $db->Execute("SELECT customers_id FROM " . TABLE_CUSTOMERS . " ORDER BY customers_id ASC");
        while (!$customers->EOF) {
                $customers_id = $customers->fields[‘customers_id’];
                $pending_rewards = $this->get_pending_rewards($customers_id);
                $db->Execute("UPDATE " . TABLE_STORE_CREDIT . "
                        SET pending = "
. $pending_rewards . "
                        WHERE customers_id = "
. $customers_id . "
                        LIMIT 1"
);
                $customers->MoveNext();
        }
}

to:

function store_pending_rewards() {
        global $db;

        $customers = $db->Execute("SELECT DISTINCT customers_id FROM " . TABLE_SC_REWARD_POINT_LOGS . " ORDER BY customers_id ASC");
        while (!$customers->EOF) {
        $customers_id = $customers->fields[‘customers_id’];
        $pending_rewards = $this->get_pending_rewards($customers_id);
        if($pending_rewards == 0.0) { $customers->MoveNext(); continue; }
                $db->Execute("UPDATE " . TABLE_STORE_CREDIT . "
                SET pending = "
. $pending_rewards . "
                WHERE customers_id = "
. $customers_id . "
                LIMIT 1"
);
                $customers->MoveNext();
        }
}

Thanks to that, only customers who actually have some pending points will be processed.


Continue Reading

Query Log v1.5.1 released

0

Version v1.5.1 of Query Log is available. You can download it from: www.data-diggers.com/contribs/query-log/downloads/querylog-current.zip .

What’s new in this version:

  • You can now close ‘calculator’ layer (it’s the tool that highlights queries that match given regular expression)
  • You can now disable query logging completely. In previous versions Query Log kept all queries in memory, no matter if You wanted to log them (display them) or not.

Continue Reading

Speed up ‘Order history’ query by 50%-75%

0

I noticed that following query takes long time to execute:

SELECT DISTINCT op.products_id
FROM orders o, orders_products op, products p
WHERE o.customers_id = ’2345′
AND o.orders_id = op.orders_id
AND op.products_id = p.products_id
AND p.products_status = ’1′
GROUP BY products_id
ORDER BY o.date_purchased DESC
LIMIT 6

I noticed that there’s no index on orders table on customers_id field. Without it MySQL has to scan whole table to find orders by customers_id (in this case ’2345′). If orders table is small there’s no problem, but when it has 10 000 or more entries it can noticably slow down Zen Cart. So, let’s add index on that table

ALTER TABLE `orders` ADD INDEX `idx_cid_datepurchased`(`customers_id`, `date_purchased`);

I included date_purchased in index, because some pages in admin area will use it for searching all orders of given customer.

In my case it decreased query time from 0.3 sec to 0.08 sec. It’s still too much, but it’s better then nothing.


Continue Reading

Query Cache v1.6 released

8

New version of Query Cache is available. If You have lots of categories in Your store, this release is a must. Download new version here. Version 1.6 adds following features:

  • Option to prefetch products_to_categories table for faster execution of zen_get_categories_products_list() function. You can turn ON/OFF this functionality by changing QC_ZEN_GET_CATEGORIES_PRODUCTS_LIST_PREFETCH switch in includes/extra_configures/query_cache.php. If Your store executes thousands of queries it’s pretty good chance that this option will solve it.
  • Query Cache can now work in Admin area too. Just enable QC_ENABLE_IN_ADMIN in admin/includes//extra_configures/query_cache.php.

By default new switches are set to false. If You have many (at least few hundreds) products linked to many categories prefetching products_to_categories table will probably improve performance. On one store this switch managed to reduce query count from 15 000 queries ( yes, 15 thousands queries!) to about 100 queries (99,3% less queries!).

If You’ll find any bugs, please report back.

Posted in: Performance, Query Cache

Continue Reading

Query Cache v1.5 released

2

Version 1.5 of Query Cache for Zen Cart has been released. New version reduces query count by 80% (previous version reduced query count by ‘only’ 50%). Here’s list of changes:

  • 970 queries down to 198 queries ( v1.0 executed about 450 queries )
  • some performance improvements to code
  • includes/functions/functions_categories.php has been rewritten to use cache and prefetch data. It reduces query count by about 100 queries (it depends on number of categories in Your store)
  • basic queries for product from products table (for example “select products_name, manufacturers_id from products where products_id = ’7′“) can now be rewritten to “select * from products where products_id = ’7′“. It saves about 100 queries on default Zen Cart demo store.

Download Query Cache v1.5. See updated blog entry on Query Cache for updated charts, demo stores and screencast.

Stay in touch

Just type Your address here to be notified of new versions of Query Cache (You’ll receive only updates on Query Cache). Quick info: We hate spam, Your email will not be given to anyone.


Continue Reading

InnoDB vs MyISAM performance in Zen Cart. Which is better?

7

Zen Cart uses MyISAM tables to store data, but MySQL offers other storage engines too. Is MyISAM the best choice? Is it the fastest one? These questions will be answered.. right now: No, it isn’t (at least not always). Read below to find out more.

Performance test

Note: In test We used MySQL 5.0.41. Results can vary depending on MySQL version You use.

Let’s find out which of the two is faster. To do this We’ll need to test their performance. We created Java application which executes typical SELECT queries against Zen Cart demo store database and measures query performance. Here are some of those queries:

SELECT queries

SELECT SQL_NO_CACHE count(*) AS total
FROM products p, products_to_categories p2c
WHERE p.products_id = p2c.products_id
AND p.products_status = ’1′
AND p2c.categories_id = ’22′
SELECT SQL_NO_CACHE products_type
FROM products
WHERE products_id = ’12′
SELECT SQL_NO_CACHE DISTINCT p.products_id, p.products_image, pd.products_name, p.master_categories_id
FROM (products p
LEFT JOIN featured f ON p.products_id = f.products_id
LEFT JOIN products_description pd ON p.products_id = pd.products_id )
WHERE p.products_id = f.products_id
AND p.products_id = pd.products_id
AND p.products_status = 1 AND f.STATUS = 1
AND pd.language_id = ’1′

Note that We added SQL_NO_CACHE to prevent MySQL from caching query results.

Now, it’s important to simulate many customers wandering around Zen Cart store. Therefore We used 10 threads to send queries to database.

InnoDB managed to perform 1186 queries per second on average, where MyISAM executed only 958 queries per second on average. InnoDB was faster by almost 25%!

Locking strategy

Very important feature (from performance perspective) is that InnoDB uses per row locking, where MyISAM uses table locking. What does it mean? We’ll clarify it with example.

Let’s assume that We’re executing following update against products table:

UPDATE products
SET products_ordered = products_ordered + 1
WHERE products_id = 12

and other thread (other http request from other customer) is executing at the same time following query:

SELECT products_type
FROM products
WHERE products_id = ’17′

Because MyISAM uses table locking when updates are made to tables, it will prevent execution of other SELECT queries until update statement finishes, even if those queries don’t look at updated rows.

InnoDB on the other hand will lock only row with products_id field set to 17, allowing concurrent execution of SELECT queries (unless those queries are asking for data from updated row).

It does not give much performance boost when Your store has low traffic, but when it’ll get more popular (hopefully) and You’ll have ten thousands visits per day it’ll make a difference ( the more traffic You’ll get the bigger the difference should be).

How to convert MyISAM table to InnoDB table

To convert any table example to InnoDB execute following SQL code:

ALTER TABLE example ENGINE = InnoDB

Unfortunately Zen Cart database contains about 80 tables, so changing each of them by hand would be inconvenient. Also, one may want to change back to MyISAM for some reason, and it would have to repeat whole process again. To address that problem We created simple Zen Cart contribution that automates conversion from MyISAM to InnoDB. You can download it here:

Download Change Storage Engine

Installation is very easy, just copy unzipped folder to Your store directory. This contribution does not overwrite any Zen Cart files, so You don’t have to worry about that. To change all tables in Your database from MyISAM/InnoDB to InnoDB/MyISAM go to Tools->Change Storage Engine and click ‘Change’. That’s it!

Summary

InnoDB is faster then MyISAM engine, it also scales better. But before You change all Your tables to InnoDB make sure to (as always) make backup of Your database. Also, after changing tables to InnoDB check if Your store runs faster as MySQL performance differs from version to version.

Updates

Version 1.1 of Change Storage Engine is available (use link above, it always points to newest version). It’ll omit MyISAM tables with FULLTEXT indexes (InnoDB does not support FULLTEXT indexes).


Continue Reading

Social Stuff

Donate

If You like Query Cache, Query Log or Randomized Tests please make a $5 donation.

Search the blog