Помощь Долго прогружается первая страница - модуль категорий.

У меня сайт с 200 000 товаров. Была такая же проблема. Всё упиралось в медленные ответы mysql. Установите для начала Для просмотра ссылки Войди или Зарегистрируйся и посмотрите время которое уходит на запросы.
Если затык в базе, то я вижу 2 решения:
1. Кеширование
2. Изменение структуры бд и переделка движка
Я для себя выбрал первый вариант потому что он проще для меня реализуем.
 
Установите для начала Для просмотра ссылки Войди или Зарегистрируйся и посмотрите время которое уходит на запросы.
Как понять что перегружает запрос ? На что обращать внимание и как с этим бороться? Вот мой запрос выделенный красным в отладчике. кеширование включено
Код:
SELECT DISTINCT *, pd.name AS name, p.image, m.name AS manufacturer, (SELECT price FROM oc_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < '2013-11-27 22:23:00') AND (pd2.date_end = '0000-00-00' OR pd2.date_end > '2013-11-27 22:23:00')) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM oc_product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < '2013-11-27 22:23:00') AND (ps.date_end = '0000-00-00' OR ps.date_end > '2013-11-27 22:23:00')) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special, (SELECT points FROM oc_product_reward pr WHERE pr.product_id = p.product_id AND customer_group_id = '1') AS reward, (SELECT ss.name FROM oc_stock_status ss WHERE ss.stock_status_id = p.stock_status_id AND ss.language_id = '1') AS stock_status, (SELECT wcd.unit FROM oc_weight_class_description wcd WHERE p.weight_class_id = wcd.weight_class_id AND wcd.language_id = '1') AS weight_class, (SELECT lcd.unit FROM oc_length_class_description lcd WHERE p.length_class_id = lcd.length_class_id AND lcd.language_id = '1') AS length_class, (SELECT AVG(rating) AS total FROM oc_review r1 WHERE r1.product_id = p.product_id AND r1.STATUS = '1' GROUP BY r1.product_id) AS rating, (SELECT COUNT(*) AS total FROM oc_review r2 WHERE r2.product_id = p.product_id AND r2.STATUS = '1' GROUP BY r2.product_id) AS reviews, p.sort_order FROM oc_product p LEFT JOIN oc_product_description pd ON (p.product_id = pd.product_id) LEFT JOIN oc_product_to_store p2s ON (p.product_id = p2s.product_id) LEFT JOIN oc_manufacturer m ON (p.manufacturer_id = m.manufacturer_id) WHERE p.product_id = '43' AND pd.language_id = '1' AND p.STATUS = '1' AND p.date_available <= '2013-11-27 22:23:00' AND p2s.store_id = '0'

www\vqmod\vqcache\vq2-catalog_model_catalog_product.php (30)
 
Этот запрос выдаёт информацию о товаре с id = 43 по состоянию на 2013-11-27 22:23:00, а именно название, скидочную цену, изображение, количество просмотров (при этом похоже что вычисляется какле-то среднее количество просмотров товаров) и что-то ещё. Я думаю что этот запрос приводит к обработке MySQL с большого обьёма данных, потому так медленно он выполняется. В этом запросе MySQL будет выдавать ответы из кэша в том случае если этот запрос уже производился в течении текущей минуты.
В стандартной сборке ocStore-1.5.5.1.1 как раз для кэширования введена переменная NOW которая подставляет в MySQL запрос вместо текущего времени текущее время, "округлённое" до секунд. Механизм таков: если идут 2 запроса вида SELECT DISTINCT ... pd2.date_start < '2013-11-27 22:23:01') и SELECT DISTINCT ... pd2.date_start < '2013-11-27 22:23:02'), MySQL не берёт данные их кэша для ответа второго запроса, потому что запросы разные. При использовании Переменной NOW запросы "округляются" до SELECT DISTINCT ... pd2.date_start < '2013-11-27 22:23:00') и SELECT DISTINCT ... pd2.date_start < '2013-11-27 22:23:00'), то есть получаются 2 одинаковых запроса, и MySQL закэшированый ответ первого запроса передаёт в качестве ответа второго запроса, при втором запросе происходит чтение из кэша.
Улучшить кэширование запроса позволит изменение в файле catalog\model\catalog\product.php.
PHP:
Вот это
    public function __construct($registry) {
        $this->NOW = date('Y-m-d H:i') . ':00';
        parent::__construct($registry);
    }
можно заменить на
        public function __construct($registry) {
                $this->NOW = date('Y-m-d') . ' 23:59:59';
                parent::__construct($registry);
        }
После такой замены MySQL будет выдавать ответы из кэша в том случае если этот запрос уже производился в течении текущих суток.

Если ваш сайт тормозит при открытии именно главной страницы, можно сделать время жизни кэша одни сутки и вначале суток, скажем в 00:02, открывать главную страницу. При этом все последующие открытия главной страницы сайта в этот день будут приводить к выдачи ответов MySQL из кэша.
 
  • Заблокирован
  • #14
а ты попробуй етим сервисом проверить что грузит сильнее всего и потом поправь Для просмотра ссылки Войди или Зарегистрируйся
 
Такой вопрос: Есть Для просмотра ссылки Войди или Зарегистрируйся
После добавления около 30 тыс товаров, стала очень медлено грузится первая страница.
Перевели на MSQLI - стало чуть быстрее, но все же тормозит.

Подтормаживает сам модуль вывода категорий. Может есть какие нибуть решения этой проблемы?
Все проблемы в модуле категорий (проверенно не раз).

Сайт не открывается но для посетителей форума напишу решение проблемы - в конроллере шапки, где формируется список категорий убираем подсчёт колличества товаров в категории, - в контроллере модуля категорий удалить подсчёт колличества товаров в категориях.

Основные тормоза проявляются именно в данном подсчёте (при колличестве товаров 30000 при каждой перезагрузке проходит 60000 запросов к базе, отсюда и тормоза)
 
на сайте (когда он работал) подсчет количества категорий был выключен. специально обратил на это внимание при анализе, так что проблема скорее всего не в этом
 
Делюсь своим решением:
1. Ставим Для просмотра ссылки Войди или Зарегистрируйся - для удобства
2. Ставим модифицированый opencart-mysql-cache. Для этого распаковываем файлы из архива в корень магазина, в config.php прописываем СВОЙ ПУТЬ папки cache_sql
PHP:
define('DIR_CACHE_SQL', 'Z:\home\localhost\www\Tests\m154/system/cache_sql/');
затем
PHP:
define('DB_DRIVER', 'mysql');
меняем на
PHP:
define('DB_DRIVER', 'mysql_cached');
//define('DB_DRIVER', 'mysql');
и в startup.php после
PHP:
require_once(DIR_SYSTEM . 'library/cache.php');
дописываем
PHP:
require_once(DIR_SYSTEM . 'library/cache_sql.php');
3. Загружаем на сервер файл query2.php, меняем в нём параметры в подключения к серверу MySql и в 55 строке указываем ваш путь в папке cache_sql
4. Ставим AutoIt, редактируем скрипт bot.au3, меняя в нём mysite.ru на адрес вашего сайта, 2013-12-31 на дату последнего дня текущего месяца (если нужно), в части строки %20p2c.category_id%20=%20'60' меняем 60 на номер первой ПОДкатегории с товарами, в части строки %20p2c.category_id%20=%20'61' меняем 61 на номер второй ПОДкатегории с товарами и т.д., в строке "$URL = $StartUrl[$j] & $i*15 & ",15"" меняем 15 на ваше количество товаров на странице
Для снижения нагрузки можно поменять Sleep(60) на Sleep(5000) (сменить паузу между запросами с 60мс увеличить до 5сек).
Внимание! Данное решение делалось для ocStore 1.5.4, под версию 1.5.5 оно не подходит.
Работает всё следующим образом. Установка модифицированого opencart-mysql-cache позволяет сохранять ответы mysql на жёсткий диск сервера. Когда запрос выполняется первый раз, он отправляется mysql серверу и его ответ сохраняется на диске, если этот же запрос выполняется снова, то он не отправляется на mysql сервер и считывается из дискового файлового кэша. При работе opencart с большим количеством товаров есть один запрос, на который приходится 90-99% времени всех запросов. У меня этот запрос выполняется без кэша примерно за 5 сек. Чтобы уменьшить время на mysql запросы достаточно закэшировать ответ на этот запрос. Для кэширования я использую скрипт bot.au3 который отправляет этот запрос (точнее несколько запросов такого типа) на сервер посредством скрипта query2.php.
Для запуска скрипта bot.au3 который инициирует кэширование медленных запросов opencarta по нему надо 'кликнуть'.
Указанные действия позволяют снизить время генерации страницы до 0.23 сек при количестве товаров 200 000.
P.S. простите за плохой код, делалось для себя на скорую руку
 

Вложения

  • qu.jpg
    qu.jpg
    104 KB · Просмотры: 12
  • opencart-mysql-cache.zip
    6,9 KB · Просмотры: 9
  • scripts.zip
    1,7 KB · Просмотры: 9
Сайт не работает
 
У меня была такая проблема, на 1.5.1.3 после обновления версии исчезло.
 
Назад
Сверху