Jump to content

Edit History

AfterGlow93

AfterGlow93

Hi, 

I had a module customized for my business and i am facing speed issues on listing

The issue seems to come from the function getproducts.

The query in this function gets products informations from database from multiple product ids.

When i execute this query on mysql client, this query take less than 1 second to finish.

But, when processed through the controller i use for my module, i can see that each product id is processed as unique, creating multiple subqueries and slowing down the whole rendering of the module page.

When i show a simple product-list from a category, with more than 100.000 products, the page load in less than 1 second. I would like to understand why, is it the function itself, or something missing here that can slow down 10x the load time by processing each product id itself ?

Here is my getproduct code :

    public function getProducts($where, $id_lang, $p, $n, $order_by = null, $order_way = null, $get_total = false, $active = true, $random = false, $random_number_products = 1, $check_access = true, Context $context = null)
    {
        # validate module
        unset($check_access);
        if (!$context) {
            $context = Context::getContext();
        }
        $front = true;
        if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) {
            $front = false;
        }
        if ($p < 1) {
            $p = 1;
        }
        $id_supplier = (int) Tools::getValue('id_supplier');

		
		        if ($get_total) {
            $sql = 'SELECT COUNT(cp.`id_product`) AS total
                FROM `' . _DB_PREFIX_ . 'product` p
                ' . Shop::addSqlAssociation('product', 'p') . '
                LEFT JOIN `' . _DB_PREFIX_ . 'category_product` cp ON p.`id_product` = cp.`id_product`
                ' . $where . '
                ' . ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') .
                    ($active ? ' AND product_shop.`active` = 1' : '') .
                    ($id_supplier ? 'AND p.id_supplier = ' . (int) $id_supplier : '');
            return (int) Db::getInstance()->getValue($sql);
        }
		
        $sql = 'SELECT DISTINCT p.id_product, p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, product_attribute_shop.`id_product_attribute`, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, pl.`description`, pl.`description_short`, pl.`available_now`,
                pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, m.`name` AS manufacturer_name, cl.`name` AS category_default,
                DATEDIFF(product_shop.`date_add`, DATE_SUB(NOW(),
                INTERVAL ' . (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20) . '
                    DAY)) > 0 AS new, product_shop.price AS orderprice
            FROM `' . _DB_PREFIX_ . 'category_product` cp
            INNER JOIN `' . _DB_PREFIX_ . 'product` p
                ON p.`id_product` = cp.`id_product`
            ' . Shop::addSqlAssociation('product', 'p') . '
            LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
            ON (p.`id_product` = pa.`id_product`)
            ' . Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1') . '
            ' . Product::sqlStock('p', 'product_attribute_shop', false, $context->shop) . '
            LEFT JOIN `' . _DB_PREFIX_ . 'category_lang` cl
                ON (product_shop.`id_category_default` = cl.`id_category`
                AND cl.`id_lang` = ' . (int) $id_lang . Shop::addSqlRestrictionOnLang('cl') . ')
            LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl
                ON (p.`id_product` = pl.`id_product`
                AND pl.`id_lang` = ' . (int) $id_lang . Shop::addSqlRestrictionOnLang('pl') . ')
            LEFT JOIN `' . _DB_PREFIX_ . 'manufacturer` m
                ON m.`id_manufacturer` = p.`id_manufacturer`
            ' . $where . '
                ' . ($active ? ' AND product_shop.`active` = 1' : '')
                . ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')
                . ($id_supplier ? ' AND p.id_supplier = ' . (int) $id_supplier : '')
                . (Tools::getValue('filter_cat') ? ' AND cp.id_category='. (int) Tools::getValue('filter_cat') : '');
				
				            $orderby = 'p.price';
            if (Tools::getValue('order') == 'product.position.asc') {
                $orderby = 'cp.position ASC';
            }
            if (Tools::getValue('order') == 'product.name.asc') {
                $orderby = 'pl.name ASC';
            }
            if (Tools::getValue('order') == 'product.name.desc') {
                $orderby = 'pl.name DESC';
            }
            if (Tools::getValue('order') == 'product.price.asc') {
                $orderby = 'product_shop.price ASC';
            }
            if (Tools::getValue('order') == 'product.price.desc') {
                $orderby = 'product_shop.price DESC';
            }

            $sql .= ' ORDER BY ' . $orderby;

        $result = Db::getInstance()->executeS($sql);

        if (!$result) {
            return array();
        }
        return Product::getProductsProperties($id_lang, $result);
    }

Thanks for help

AfterGlow93

AfterGlow93

Hi, 

I had a module customized to my business and i am facing speed issues on listing

The issue seems to come from the function getproducts.

The query in this function gets products informations from database from multiple product ids.

When i execute this query on mysql client, this query take less than 1 second to finish.

But, when processed through the controller i use for my module, i can see that each product id is processed as unique, creating multiple subqueries and slowing down the whole rendering of the module page.

When i show a simple product-list from a category, with more than 100.000 products, the page load in less than 1 second. I would like to understand why, is it the function itself, or something missing here that can slow down 10x the load time by processing each product id itself ?

Here is my getproduct code ; 

    public function getProducts($where, $id_lang, $p, $n, $order_by = null, $order_way = null, $get_total = false, $active = true, $random = false, $random_number_products = 1, $check_access = true, Context $context = null)
    {
        # validate module
        unset($check_access);
        if (!$context) {
            $context = Context::getContext();
        }
        $front = true;
        if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) {
            $front = false;
        }
        if ($p < 1) {
            $p = 1;
        }
        $id_supplier = (int) Tools::getValue('id_supplier');

		
		        if ($get_total) {
            $sql = 'SELECT COUNT(cp.`id_product`) AS total
                FROM `' . _DB_PREFIX_ . 'product` p
                ' . Shop::addSqlAssociation('product', 'p') . '
                LEFT JOIN `' . _DB_PREFIX_ . 'category_product` cp ON p.`id_product` = cp.`id_product`
                ' . $where . '
                ' . ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') .
                    ($active ? ' AND product_shop.`active` = 1' : '') .
                    ($id_supplier ? 'AND p.id_supplier = ' . (int) $id_supplier : '');
            return (int) Db::getInstance()->getValue($sql);
        }
		
        $sql = 'SELECT DISTINCT p.id_product, p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, product_attribute_shop.`id_product_attribute`, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, pl.`description`, pl.`description_short`, pl.`available_now`,
                pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, m.`name` AS manufacturer_name, cl.`name` AS category_default,
                DATEDIFF(product_shop.`date_add`, DATE_SUB(NOW(),
                INTERVAL ' . (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20) . '
                    DAY)) > 0 AS new, product_shop.price AS orderprice
            FROM `' . _DB_PREFIX_ . 'category_product` cp
            INNER JOIN `' . _DB_PREFIX_ . 'product` p
                ON p.`id_product` = cp.`id_product`
            ' . Shop::addSqlAssociation('product', 'p') . '
            LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
            ON (p.`id_product` = pa.`id_product`)
            ' . Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1') . '
            ' . Product::sqlStock('p', 'product_attribute_shop', false, $context->shop) . '
            LEFT JOIN `' . _DB_PREFIX_ . 'category_lang` cl
                ON (product_shop.`id_category_default` = cl.`id_category`
                AND cl.`id_lang` = ' . (int) $id_lang . Shop::addSqlRestrictionOnLang('cl') . ')
            LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl
                ON (p.`id_product` = pl.`id_product`
                AND pl.`id_lang` = ' . (int) $id_lang . Shop::addSqlRestrictionOnLang('pl') . ')
            LEFT JOIN `' . _DB_PREFIX_ . 'manufacturer` m
                ON m.`id_manufacturer` = p.`id_manufacturer`
            ' . $where . '
                ' . ($active ? ' AND product_shop.`active` = 1' : '')
                . ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')
                . ($id_supplier ? ' AND p.id_supplier = ' . (int) $id_supplier : '')
                . (Tools::getValue('filter_cat') ? ' AND cp.id_category='. (int) Tools::getValue('filter_cat') : '');
				
				            $orderby = 'p.price';
            if (Tools::getValue('order') == 'product.position.asc') {
                $orderby = 'cp.position ASC';
            }
            if (Tools::getValue('order') == 'product.name.asc') {
                $orderby = 'pl.name ASC';
            }
            if (Tools::getValue('order') == 'product.name.desc') {
                $orderby = 'pl.name DESC';
            }
            if (Tools::getValue('order') == 'product.price.asc') {
                $orderby = 'product_shop.price ASC';
            }
            if (Tools::getValue('order') == 'product.price.desc') {
                $orderby = 'product_shop.price DESC';
            }

            $sql .= ' ORDER BY ' . $orderby;

        $result = Db::getInstance()->executeS($sql);

        if (!$result) {
            return array();
        }
        return Product::getProductsProperties($id_lang, $result);
    }

Thanks for help

×
×
  • Create New...