N
N
nikkon822019-02-06 11:07:44
opencart
nikkon82, 2019-02-06 11:07:44

How to fix slow requests when filtering on the site?

Good afternoon!
Please help with a slow request when filtering
. On a page with 4000 products, the filter shows products quickly, but filters are updated 2 more seconds from above (takes from product attributes).
In the slow query logs, this is:
1 0x1FEE9AB6025C7FCB 24.4336 36.3% 19 1.2860 0.19 SELECT oc_product_attribute oc_attribute_description
SELECT pa.product_id, MAX(ad.attribute_id) as attribute_id, MAX(ad.name) as attribute_name, MAX(pa.text) text, COUNT(*) total FROM `oc_product_attribute` pa LEFT JOIN `oc_attribute_description` ad ON ad. attribute_id = pa.attribute_id WHERE pa.product_id IN (4728,4729,2280,2289,2290,2297,2298,2299,2300,4730,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326 /*... omitted 4043 items ...*/) GROUP BY lower(pa.text), a.attribute_id HAVING COUNT(*) > 0\G
Controller code:

/* attributes */
        $results = $this->model_journal2_super_filter->getAttributes($data);
        foreach ($results as $key => $result) {
            $display_mode = Journal2Utils::getProperty($module_data, 'attributes.' . $key, 'on');
            if ($display_mode === 'off') {
                continue;
            }
            $values = array();
            foreach ($result['values'] as $value) {
                $values[] = array(
                    'text'		=> rawurlencode(trim($value['text'])),
                    'name'		=> trim($value['text']) . ( $show_product_count ? ' (' . $value['total'] . ')' : ''),
                    'keyword'	=> $this->keyword($result['attribute_name'] . " " . $value['text'])
                );
            }
            $this->data['attribute'] = array(
                'attribute_id'		=> $result['attribute_id'],
                'attribute_name'	=> $result['attribute_name'],
                'display_mode'		=> $display_mode,
                'type'              => Journal2Utils::getProperty($module_data, 'attributes_type.' . $key, 'multi'),
                'values'			=> $values,
            );
      $this->data['count_attr'] = count($this->data['attribute']['values']);
            $this->template = 'journal2/module/super_filter_attributes.tpl';
            $filter_groups[] = array(
                'sort_order'    => Journal2Utils::getProperty($module_data, 'sort_orders.a_' . $result['attribute_id']),
                'html'          => $this->render()
            );
        }

Model:
public function getAttributes($data = array()){
        if(isset($data['attributes']) && !empty($data['attributes'])) {
            $product_attributes = $this->getProductAttributes($data);
            foreach ($data['attributes'] as $attribute_id => $value) {
                foreach($product_attributes as $key => $attribute) {
                    if($key == $attribute_id) {
                        unset($product_attributes[$key]);
                    }
                }

                $temp_data = $data;
                unset($temp_data['attributes'][$attribute_id]);
                foreach($this->getProductAttributes($temp_data) as $key => $attribute){
                    if($key == $attribute_id) {
                        $product_attributes[$attribute_id] = $attribute;
                    }
                }
            }

            $results = $product_attributes;
        }else{
            $results = $this->getProductAttributes($data);
        }

        ksort($results);
        return $results;
    }

    private function getProductAttributes($data = array()){
        $data['start'] = 0;
        $data['limit'] = PHP_INT_MAX;

        $products = $this->getProducts($data);

        if (count($products) == 0) {
            return array();
        }

        $sql = "SELECT pa.product_id, MAX(ad.attribute_id) as attribute_id, MAX(ad.name) as attribute_name, MAX(pa.text) text, COUNT(*) total FROM `". DB_PREFIX . "product_attribute` pa LEFT JOIN `". DB_PREFIX . "attribute_description` ad ON ad.attribute_id = pa.attribute_id";

        $sql .= " WHERE pa.product_id IN (" . implode(",", $products) . ")";

        //$sql .= " AND pa.language_id = '" . (int)$this->config->get('config_language_id') . "' AND ad.language_id = '" . (int)$this->config->get('config_language_id') . "'";

        $sql .= " GROUP BY lower(pa.text), ad.attribute_id HAVING COUNT(*) > 0";

        $query = $this->db->query($sql);

        $results = array();

        foreach ($query->rows as $row) {
            if (!isset($results[$row['attribute_id']])) {
                $results[$row['attribute_id']] = array(
                    'attribute_id'          => $row['attribute_id'],
                    'attribute_name'        => $row['attribute_name'],
                    'values'                => array()
                );
            }
            $results[$row['attribute_id']]['values'][] = array(
                'text'                  => $row['text'],
                'total'                 => $row['total'],
            );
        }

        foreach ($results as $attribute_id => &$value) {
            usort($value['values'], array('ModelJournal2SuperFilter', 'cmpAttrs'));
        }

        return $results;
    }

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question