I have about 120 000 products across 9000 categories, with more then 800 000 references between them (each product belongs to 7 categories in average).
Latest CS-Cart (4.1.3 at the moment) runs on VPS with 4GB RAM, single-core configuration. Cache is stored in the database (mySQL with myISAM tables and mySQLi mode).
Memory_limit for PHP 5.5 is set for 2GB.
Every page takes about 5-10 seconds to load. Bottleneck is SQL queries, that sometimes take up to 30 seconds to build up their data.
For examples, there are such monsters as:
SELECT SQL_CALC_FOUND_ROWS products.*, descr1.product as product, MIN(IF(prices.percentage_discount = 0, prices.price, prices.price - (prices.price * prices.percentage_discount)/100)) as price, GROUP_CONCAT(IF(products_categories.link_type = 'M', CONCAT(products_categories.category_id, 'M'), products_categories.category_id)) as category_ids, products_categories.position, IF(shared_descr.product_id IS NOT NULL, shared_descr.product, descr1.product) as product, IF(shared_descr.product_id IS NOT NULL, shared_descr.short_description, descr1.short_description) as short_description, IF(shared_descr.product_id IS NOT NULL, IF(shared_descr.short_description = '', shared_descr.full_description, ''), IF(descr1.short_description = '', descr1.full_description, '')) as full_description, IF(shared_descr.product_id IS NOT NULL, shared_descr.meta_keywords, descr1.meta_keywords) as meta_keywords, IF(shared_descr.product_id IS NOT NULL, shared_descr.meta_description, descr1.meta_description) as meta_description, IF(shared_descr.product_id IS NOT NULL, shared_descr.search_words, descr1.search_words) as search_words, IF(shared_descr.product_id IS NOT NULL, shared_descr.promo_text, descr1.promo_text) as promo_text, IF(shared_prices.product_id IS NOT NULL,MIN(IF(shared_prices.percentage_discount = 0, shared_prices.price, shared_prices.price - (shared_prices.price * shared_prices.percentage_discount)/100)),MIN(IF(prices.percentage_discount = 0, prices.price, prices.price - (prices.price * prices.percentage_discount)/100))) as price, 100 - ((prices.price * 100) / list_price) AS sales_discount FROM cscart_products as products LEFT JOIN cscart_product_descriptions as descr1 ON descr1.product_id = products.product_id AND descr1.lang_code = 'ru' LEFT JOIN cscart_product_prices as prices ON prices.product_id = products.product_id AND prices.lower_limit = 1 INNER JOIN cscart_products_categories as products_categories ON products_categories.product_id = products.product_id INNER JOIN cscart_categories ON cscart_categories.category_id = products_categories.category_id AND (cscart_categories.usergroup_ids = '' OR FIND_IN_SET(0, cscart_categories.usergroup_ids) OR FIND_IN_SET(1, cscart_categories.usergroup_ids)) AND cscart_categories.status IN ('A', 'H') LEFT JOIN cscart_ult_product_descriptions shared_descr ON shared_descr.product_id = products.product_id AND shared_descr.company_id = 1 AND shared_descr.lang_code = 'ru' LEFT JOIN cscart_ult_product_prices as shared_prices ON shared_prices.product_id = products.product_id AND shared_prices.lower_limit = 1 AND shared_prices.usergroup_id IN (0, 0, 1) AND shared_prices.company_id = 1 WHERE 1 AND cscart_categories.company_id = 1 AND (products.usergroup_ids = '' OR FIND_IN_SET(0, products.usergroup_ids) OR FIND_IN_SET(1, products.usergroup_ids)) AND products.status IN ('A') AND prices.usergroup_id IN (0, 0, 1) GROUP BY products.product_id HAVING sales_discount > 0 ORDER BY sales_discount desc LIMIT 0, 8
Any advice how to handle such load?
I foresee, that these queries ate too complicated, and optimizing mySQL engine would not help much. Are there any other options to consider?