[Помогите] OpenCart 2 тормоза 7-9 сек.

Тема в разделе "OpenCart", создана пользователем Andrey789, 31 июл 2017.

  1. Andrey789

    Andrey789

    Регистрация:
    31 июл 2017
    Сообщения:
    6
    Симпатии:
    0
    Приветствую друзья, решил обратиться к Вам за советом, просьба помочь кто чем может )

    Сайт дико тормозит...
    Среднее время обработки страницы 7-10 сек.
    Подсчет количества товара в категориях - выключен.

    Движек 2.3.0.2
    php 7
    gzip включен
    Nginx 1.10.2 - но дело не в нем, админ сервера смотрел, и говорит что к нему такие уже долетают...

    Относительно БД цитата админа:
    Код:
    судя по трейсу, в код обращения к базе потребляет менее 1% времени
    и в мускуле нет медленных запросов
    по крайней мере длиннее 1 секунды
    С помощью Xdebug 2 (https://xdebug.org/docs/profiler) протестировали работу сайта,
    вот результат: https://cloud.mail.ru/public/Hqtk/399pGsnms но по медленным запросам жалоб нет.
    Проблема появлялась постепенно, по ходу наполнения сайта...

    А вот в логах по количеству запросов беда,
    Вот лог по количеству запросов: https://cloud.mail.ru/public/DN9V/Uz8FpXCSp

    572 раза делается запрос:
    Код:
    SELECT keyword FROM oc_url_alias WHERE `query` = 'route=product/category'
    он конечно закэшировался в мускуле, но обработка ответа на стороне php тоже занимет время.

    Понял что это маскировка ссылки, но почему 572 раза обращается к sql за один вызов страницы, не понимаю...
    А в общем, там 2914 запросов за один раз...
    просто этот запрос примечателен тем, что он ничего не возвращает

    Товара: 5200 скоро будет больше,
    Модули для сео установлен Complete SEO Package. он и генерит чпу.
    Помогите пожалуйста избавиться от этих тормозов...
     
    Последнее редактирование: 31 июл 2017
  2. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    В стандартной системе ЧПУ в ОК нет кеширования, поэтому запрос отрправляется по каждой ссылке, а ссылок на странице может быть сколько угодно. Одно только меню может содержать несколько сотен ссылок.

    Вам нужно сделать 2 вещи: поставить SeoPro и проверить индексы в базе. Хотя вы говорите, что медленных запросов нет, но у вас симптомы отсутствия некоторых нужных индексов (рост тормозов с ростом количества товаров).
     
  3. Andrey789

    Andrey789

    Регистрация:
    31 июл 2017
    Сообщения:
    6
    Симпатии:
    0
    Если вы рекомендуете покупать SeoPro для генерации кеша, то как я уже выше говорил, я использую Complete SEO Package который имеет функцию массовой генерации урл, массового кеширования урл, и удаления дубликатов урл.
    Все это уже сделано.
    Если не для этого, то поправьте меня пожалуйста.

    А вот что касается отсутствия некоторых нужны индексов, то база проиндексирована, но не исключается что может быть что-то действительно не так сделано, просьба подсказать на что, и как смотреть для выявления этой ошибки.
     
  4. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Его не надо покупать (он бесплатный, и это не полноценный модуль) и он не для генерации кеша!
    SeoPro - это альтернативная система ЧПУ, которая значительно превосходит стандартную по совокупности свойств.

    Вы либо неправильно это называете, либо говорите вообще о другом. Речь идёт не об индексации, а о полях, который учавствуют в индексе. Там должны быть все поля по которым происходят джоины и выборки.

    Где-то в интернете ходит набор SQL запросов для генерации индексов в ОК. Не уверен, под какую он версию, но начните хоть с этих. Только лучше их не запускать скопом, а сначала через phpMyAdmin проверить каких из них не хватает и добавить только их. В дублирующих индексах нет ничего страшного, но и хорошего тоже ничего нет.
     
  5. Andrey789

    Andrey789

    Регистрация:
    31 июл 2017
    Сообщения:
    6
    Симпатии:
    0
    Вот нашел запросы для индексации таблиц:
    Код:
    ALTER TABLE oc_product_attribute ADD INDEX attribute_id ( attribute_id );
    ALTER TABLE oc_product_attribute ADD INDEX language_id ( language_id );
    
    ALTER TABLE oc_product_description ADD INDEX language_id ( language_id );
    
    ALTER TABLE oc_product_image ADD INDEX product_id ( product_id );
    ALTER TABLE oc_product_image ADD INDEX sort_order ( sort_order );
    
    ALTER TABLE oc_product_option ADD INDEX product_id (product_id);
    ALTER TABLE oc_product_option ADD INDEX option_id (option_id);
    
    ALTER TABLE oc_product_option_value ADD INDEX product_option_id (product_option_id);
    ALTER TABLE oc_product_option_value ADD INDEX product_id (product_id);
    ALTER TABLE oc_product_option_value ADD INDEX option_id (option_id);
    ALTER TABLE oc_product_option_value ADD INDEX option_value_id (option_value_id);
    ALTER TABLE oc_product_option_value ADD INDEX subtract (subtract);
    ALTER TABLE oc_product_option_value ADD INDEX quantity (quantity);
    
    ALTER TABLE oc_product_reward ADD INDEX product_id ( product_id );
    ALTER TABLE oc_product_reward ADD INDEX customer_group_id ( customer_group_id );
    
    ALTER TABLE oc_product_to_category ADD INDEX category_id ( category_id );
    
    ALTER TABLE oc_product_to_store ADD INDEX store_id ( store_id );
    
    ALTER TABLE oc_setting ADD INDEX store_id ( store_id );
    ALTER TABLE oc_setting ADD INDEX `group` ( `group` );
    ALTER TABLE oc_setting ADD INDEX `key` ( `key` );
    ALTER TABLE oc_setting ADD INDEX serialized ( serialized );
    
    ALTER TABLE oc_url_alias ADD INDEX query ( query );
    Запускал по очереди, и для каждого получал ответ:

    Код:
    Ответ MySQL: Документация
    
    #1061 - Дублирующееся имя ключа 'product_id'
    т.е. индексы для каждой таблицы уже существуют...
    как и выше уже говорил:
     
  6. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Если тормоза наростали постепенно по мере наполнения магазина, а не резко после установки какого-то модуля, то у вас есть какой-то кривой модуль, который не пригоден для большого количества товаров (а таких довольно много).
     
  7. chukcha

    chukcha

    Регистрация:
    9 окт 2014
    Сообщения:
    448
    Симпатии:
    119
    Очень конечно странный запрос.. Закешировался или нет - не важно
    Нужно искать точку генерации
     
  8. Andrey789

    Andrey789

    Регистрация:
    31 июл 2017
    Сообщения:
    6
    Симпатии:
    0
    Может быть в /catalog/controller/common/header.php есть какой-то пересчет количества, взгляните пожалуйста...

    Код:
    <?php
    class ControllerCommonHeader extends Controller {
        public function index() {
            // Analytics
            $this->load->model('extension/extension');
    
            $data['analytics'] = array();
    
            $analytics = $this->model_extension_extension->getExtensions('analytics');
    
            foreach ($analytics as $analytic) {
                if ($this->config->get($analytic['code'] . '_status')) {
                    $data['analytics'][] = $this->load->controller('extension/analytics/' . $analytic['code'], $this->config->get($analytic['code'] . '_status'));
                }
            }
    
            if ($this->request->server['HTTPS']) {
                $server = $this->config->get('config_ssl');
            } else {
                $server = $this->config->get('config_url');
            }
    
            if (is_file(DIR_IMAGE . $this->config->get('config_icon'))) {
                $this->document->addLink($server . 'image/' . $this->config->get('config_icon'), 'icon');
            }
    
            $data['title'] = $this->document->getTitle();
    
            $data['base'] = $server;
            $data['description'] = $this->document->getDescription();
            $data['keywords'] = $this->document->getKeywords();
            $data['links'] = $this->document->getLinks();
            $data['styles'] = $this->document->getStyles();
            $data['scripts'] = $this->document->getScripts();
            $data['lang'] = $this->language->get('code');
            $data['direction'] = $this->language->get('direction');
    
            $data['name'] = $this->config->get('config_name');
    
            if (is_file(DIR_IMAGE . $this->config->get('config_logo'))) {
                $data['logo'] = $server . 'image/' . $this->config->get('config_logo');
            } else {
                $data['logo'] = '';
            }
    
            $this->load->language('common/header');
    
            $data['text_home'] = $this->language->get('text_home');
    
            // Wishlist
            if ($this->customer->isLogged()) {
                $this->load->model('account/wishlist');
    
                $data['text_wishlist'] = sprintf($this->language->get('text_wishlist'), $this->model_account_wishlist->getTotalWishlist());
            } else {
                $data['text_wishlist'] = sprintf($this->language->get('text_wishlist'), (isset($this->session->data['wishlist']) ? count($this->session->data['wishlist']) : 0));
            }
    
            $data['text_shopping_cart'] = $this->language->get('text_shopping_cart');
            $data['text_logged'] = sprintf($this->language->get('text_logged'), $this->url->link('account/account', '', true), $this->customer->getFirstName(), $this->url->link('account/logout', '', true));
    
            $data['text_account'] = $this->language->get('text_account');
            $data['text_register'] = $this->language->get('text_register');
            $data['text_login'] = $this->language->get('text_login');
            $data['text_order'] = $this->language->get('text_order');
            $data['text_transaction'] = $this->language->get('text_transaction');
            $data['text_download'] = $this->language->get('text_download');
            $data['text_logout'] = $this->language->get('text_logout');
            $data['text_checkout'] = $this->language->get('text_checkout');
            $data['text_category'] = $this->language->get('text_category');
            $data['text_all'] = $this->language->get('text_all');
    
            $data['home'] = $this->url->link('common/home');
            $data['wishlist'] = $this->url->link('account/wishlist', '', true);
            $data['logged'] = $this->customer->isLogged();
            $data['account'] = $this->url->link('account/account', '', true);
            $data['register'] = $this->url->link('account/register', '', true);
            $data['login'] = $this->url->link('account/login', '', true);
            $data['order'] = $this->url->link('account/order', '', true);
            $data['transaction'] = $this->url->link('account/transaction', '', true);
            $data['download'] = $this->url->link('account/download', '', true);
            $data['logout'] = $this->url->link('account/logout', '', true);
            $data['shopping_cart'] = $this->url->link('checkout/cart');
            $data['checkout'] = $this->url->link('checkout/checkout', '', true);
            $data['contact'] = $this->url->link('information/contact');
            $data['telephone'] = $this->config->get('config_telephone');
    
            // Menu
            $this->load->model('catalog/category');
    
            $this->load->model('catalog/product');
    
            $data['categories'] = array();
    
            $categories = $this->model_catalog_category->getCategories(0);
    
            foreach ($categories as $category) {
                if ($category['top']) {
                    // Level 2
                    $children_data = array();
    
                    $children = $this->model_catalog_category->getCategories($category['category_id']);
    
                    foreach ($children as $child) {
                        $filter_data = array(
                            'filter_category_id'  => $child['category_id'],
                            'filter_sub_category' => true
                        );
    
                        $children_data[] = array(
                            'name'  => $child['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : ''),
                            'href'  => $this->url->link('product/category', 'path=' . $category['category_id'] . '_' . $child['category_id'])
                        );
                    }
    
                    // Level 1
                    $data['categories'][] = array(
                        'name'     => $category['name'],
                        'children' => $children_data,
                        'column'   => $category['column'] ? $category['column'] : 1,
                        'href'     => $this->url->link('product/category', 'path=' . $category['category_id'])
                    );
                }
            }
    
            $data['language'] = $this->load->controller('common/language');
            $data['currency'] = $this->load->controller('common/currency');
            $data['search'] = $this->load->controller('common/search');
            $data['cart'] = $this->load->controller('common/cart');
    
            // For page specific css
            if (isset($this->request->get['route'])) {
                if (isset($this->request->get['product_id'])) {
                    $class = '-' . $this->request->get['product_id'];
                } elseif (isset($this->request->get['path'])) {
                    $class = '-' . $this->request->get['path'];
                } elseif (isset($this->request->get['manufacturer_id'])) {
                    $class = '-' . $this->request->get['manufacturer_id'];
                } elseif (isset($this->request->get['information_id'])) {
                    $class = '-' . $this->request->get['information_id'];
                } else {
                    $class = '';
                }
    
                $data['class'] = str_replace('/', '-', $this->request->get['route']) . $class;
            } else {
                $data['class'] = 'common-home';
            }
    
            return $this->load->view('common/header', $data);
        }
    }
    
     
  9. Andrey789

    Andrey789

    Регистрация:
    31 июл 2017
    Сообщения:
    6
    Симпатии:
    0
    Также, забыл записать, иногда бывает так, что сайт начинает отлично работать и без кэша, допустим сейчас.
    Тоже непонятно с чем это связано...
     
    Последнее редактирование: 5 авг 2017
  10. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Есть несколько вариантов: хостинг оверселит и ваши соседи по серверу отжирают все ресурсы, поэтому ваш сайт нормально работает только когда у соседей падает нагрузка, либо у вас есть модули с проверкой лицензии в реальном времени и сервер лицензий не справляется с нагрузкой, а когда нагрузка на него падает, ваш сайт открывается нормально.
     
  11. Andrey789

    Andrey789

    Регистрация:
    31 июл 2017
    Сообщения:
    6
    Симпатии:
    0
    Я бы с Вами охотно согласился, если бы не одно но, у меня не хостинг, у меня старенький, 10 летний (личный) сервер... Не перегружен, жесткие диски живые, на нем только мои проекты.

    Опять же, я все-таки думаю что проблема в количестве запросов, так как мой админ сервера с огромным опытом, и работает в знаменитой и очень крупной компании именно админом серверов...
    Проверялись и медленные запросы, по ним нет перегрузов, перегруз именно в количестве запросов...

    Если есть умельцы, которые поймут по логам (https://cloud.mail.ru/public/DN9V/Uz8FpXCSp) запросов - причину, то отблагодарю. проблему очень нужно решить...
     
  12. chukcha

    chukcha

    Регистрация:
    9 окт 2014
    Сообщения:
    448
    Симпатии:
    119
    SELECT keyword FROM oc_url_alias WHERE `query` = 'route=product/category'
    Это вообще криврой хзапрос, и скорей всего вам его лепит
    SeoSuperPuperMegaPack
     
    cobalt нравится это.