Как оптимизировать запрос sql opencart
Перейти к содержимому

Как оптимизировать запрос sql opencart

  • автор:

Оптимизация SQL-запросов OpenCart 1.5.5.1

SourceDistillery.com - код двойной очистки от багов

В общем то все три мнения имеют право на жизнь, но споры часто достигают масштаба холивара. Беда в том, что споры эти часто теоретические. Оптимизаторы в качестве панацеи от всех бед выбирают кэширование — пытаются кэшировать все и вся. А по-моему начинать надо с оптимизации SQL-запросов, а уже потом применять кэширование.

Начальные условия

  • Интернет-магазин CD/DVD дисков.
  • Количество категорий (разделов-подразделов): 278
  • Количество товаров: 68800.
  • Атрибутов и категорий нет.
  • Магазин одноязычный.

Я выбрал себе простой сценарий тестирования: Главная страница — Страница категории — Страница подкатегории — Страница товара. Перед запуском сценария очищал кэш MySQL и файловый кэш OpenCart.

Медленные запросы

При помощи стандартного средства MySQL — журнала медленных запросов (или Slow Log) удалось обнаружить 3 самых медленных из частых запросов. Вот они:

SELECT p.product_id, (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 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 < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end >NOW())) 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 < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end >NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special FROM `oc_product_to_category` p2c LEFT JOIN `oc_product` p ON (p2c.product_id = p.product_id) 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) WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available  

(1) Запрос получает всего навсего список товаров в категории с разбивкой на страницы, с сортировкой.

SELECT COUNT(DISTINCT p.product_id) AS total FROM `oc_product_to_category` p2c LEFT JOIN `oc_product` p ON (p2c.product_id = p.product_id) 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) WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available  

(2) Запрос подсчитывает общее количество товаров в выбранной категории.

SELECT * FROM `oc_url_alias` WHERE `query` = 'product_id=46' 

(3) Формирование SEO_URL.

Третий запрос самый простой, но и его можно оптимизировать. Нужно уменьшить длину поля `query`, по-умолчанию она 255 символов, 32 символа будет достаточно. Потом надо создать индекс по этому полю. Уменьшение длины поля необходимо для того, чтобы уменьшить общий размер индекса таблицы. Если индекс помещается в CACHE_INDEX MySQL, то поиск по нему идет быстрее.

ALTER TABLE `oc_url_alias` CHANGE `query` `query` VARCHAR( 32 ) NOT NULL; ALTER TABLE `oc_url_alias` ADD INDEX `query` ( `query` ); 

Запросы (1) и (2) формируются в файле catalod/model/catalog/product.php, в методах класса ModelCatalogProduct соответственно getProduct и getTotalProducts. Будем оптимизировать PHP-код класса.

Оптимизация класса ModelCatalogProduct

Во многих контроллерах вызов методов getProducts и getTotalProducts происходит парно:

$product_total = $this->model_catalog_product->getTotalProducts($data); $results = $this->model_catalog_product->getProducts($data);

Добравив к запросу (1) параметр SQL_CALC_FOUND_ROWS можно в одном запросе не только загрузить из базы N записей, ограниченных условием LIMIT, но и подсчитать все найденные записи. Тогда запрос (2) уже будет не нужен.

Еще MySQL сам по себе кэширует результаты SQL-запросов, поэтому в дополнительном кэшировании SQL мало смысла. Только MySQL не кэширует запросы, содержащие NOW(). Заменим в запросах NOW() на date('Y-m-d H:i').':00' или даже date('Y-m-d H').':00:00' .

В самом конце метода getProducts для каждого товара вызывается другой метод getProduct

foreach ($query->rows as $result) < $product_data[$result['product_id']] = $this->getProduct($result['product_id']); >

, в котором, в свою очередь, выполняется еще один SQL-запрос:

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 < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end >NOW())) 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 < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end >NOW())) 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 = '2700' AND pd.language_id = '1' AND p.status = '1' AND p.date_available  

В этом запросе при помощи вложенных SQL-запросов вновь вычисляется цена товара с учетом скидок и акций, и вновь вычисляется звездный рейтинг товара. Можно использовать данные, полученные при помощи запроса (1).

Оптимизированный OpenCart можно потестировать. Измененные файлы доступны в виде commit.

Дальнейшая оптимизация

Для дальнейшего ускорения SQL-запроса (1) можно сделать денормализацию базы данных. В таблицу `oc_product` добавить два поля rating и reviews для хранения рейтинга товара и количества оценок, формирующих этот рейтинг. Значения полей тогда можно будет вычислять не при каждом запросе, а только при одобрении рейтинга администратором магазина.

Если отказаться от скидок и акций, то можно еще ускорить SQL-запрос (1), удалив из него подзапросы:

(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 < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end >NOW())) 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 < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end >NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special 

и заменив их на

NULL AS discount, NULL AS special

Разработка на языках: PHP, JavaScript, node.js. Базы данных: MySQL, PostgreSQL, MongoDB.
Доработка CMS: OpenCart, PrestaShop, WordPress. Интеграция с: платежными системами, ВКонтакте, Facebook, Яндекс.

Как оптимизировать sql запрос товаров opencart?

Добрый день, есть магазин на 700000 товаров.
В связи с этим страницы категорий грузятся секунд по 25.
Посмотрев какие запросы медленнее всего, нашёл 2:
getTotalProducts (Около 9 секунд)
getProducts (10-12 секунд)

Сам долгий запрос:

SELECT p.product_id, ( 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 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 < NOW()) AND ( pd2.date_end = '0000-00-00' OR pd2.date_end >NOW() ) ) 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 < NOW()) AND ( ps.date_end = '0000-00-00' OR ps.date_end >NOW() ) ) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1 ) AS special FROM oc_category_path cp LEFT JOIN oc_product_to_category p2c ON (cp.category_id = p2c.category_id) LEFT JOIN oc_product p ON (p2c.product_id = p.product_id) 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) WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available 

Сервер: 2ядра, 2gb ram.
Вопрос такой: Я знаю, что такое количесто товаро не мало, но всё же, 20 секунд это явно не нормально. Как можно оптимизировать запрос? Из-за какого подзапроса может быть такая шняга?

  • Вопрос задан более трёх лет назад
  • 641 просмотр

5 комментариев

Средний 5 комментариев

Оптимизация производительности OpenCart 3 - эффективные методы и практические советы

Оптимизация производительности OpenCart 3. Современные потребители требуют мгновенных результатов, и скорость работы вашего интернет-магазина играет ключевую роль в их удовлетворении. В этой статье мы рассмотрим эффективные методы оптимизации производительности магазина на платформе OpenCart 3, а также предоставим практические советы по улучшению скорости загрузки страниц, оптимизации изображений и использованию кеширования.

Оптимизация производительности OpenCart 3 - перечень

1. Оптимизация изображений

  • Формат и сжатие: Используйте форматы изображений с низкой степенью сжатия, такие как JPEG для фотографий и PNG для изображений с прозрачностью. Используйте инструменты для автоматического сжатия изображений без потери качества.

2. Кеширование:

  • Браузерное кеширование: Включите настройки кеширования браузера для статических ресурсов, таких как изображения и стили. Это уменьшит время загрузки при последующих посещениях.

3. Минификация CSS и JavaScript

  • Удаление лишних пробелов и комментариев: Минифицируйте CSS и JavaScript файлы, удаляя лишние пробелы, комментарии и форматирование. Это сократит объем передаваемых данных.

4. Использование системы кеширования OpenCart

  • Настройка системы кеширования: В административной панели OpenCart 3 активируйте встроенную систему кеширования. Это снизит нагрузку на сервер и ускорит загрузку страниц.

5. CDN (Content Delivery Network)

  • Интеграция с CDN: Используйте CDN для распределения контента ближе к конечным пользователям. Это уменьшит задержки при загрузке ресурсов.

6. Оптимизация запросов к Базе Данных

  • Индексация таблиц: Убедитесь, что таблицы в базе данных магазина проиндексированы правильно. Это ускорит выполнение SQL-запросов.

7. Использование кэширования платежных и доставочных систем

  • Кэширование данных платежных и доставочных систем: Включите кэширование для данных, которые редко меняются, но часто запрашиваются.

8. Оптимизация шрифтов

  • Локальные шрифты: Предпочтительно использовать локальные шрифты вместо загрузки их извне. Это уменьшит время загрузки страницы.

9. Анализ с Google PageSpeed Insights

  • Регулярный анализ: Постоянно анализируйте производительность магазина с помощью Google PageSpeed Insights и внедряйте рекомендованные улучшения.

Заключение

Эффективная оптимизация производительности магазина на OpenCart 3 требует системного подхода. Регулярно мониторьте и анализируйте производительность, внедряйте улучшения и следите за новыми технологиями в области оптимизации. Это поможет не только удовлетворить ожидания ваших клиентов, но и улучшить позиции вашего магазина в поисковых результатах.

Автор: Opencart | Дата: 26.01.2024

Модуль Упрощенный заказ на Opencart 3.0

Модуль Упрощенный заказ на Opencart 3.0

Категория: Модули Opencart

Очень мощный модуль для упрощения формы оформления заказа в Opencart 3.0. Он поможет вам сделать стр..

Модуль Купить в 1 клик Opencart 3.0

Модуль Купить в 1 клик Opencart 3.0

Категория: Модули Opencart

Модуль добавляет кнопку "Купить в 1 клик" на страницу товара и/или в списки товаров Opencart 3.0. По..

Модуль Корзина Popup для Opencart 3.0

Модуль Корзина Popup для Opencart 3.0

Категория: Модули Opencart

Всплывающая корзина на сайте Opencart 3.0 - один из способов увеличить конверсию в интернет магазине..

Модуль Менеджер заказов Opencart 3.0

Модуль Менеджер заказов Opencart 3.0

Категория: Модули Opencart

Модуль расширенного менеджера заказов Opencart 3.0 позволит удобно просматривать заказы в интернет-м..

Модуль Авторизация через соцсети Opencart 3.0

Модуль Авторизация через соцсети Opencart 3.0

Категория: Модули Opencart

Модуль для регистрации и авторизации покупателей через социальные сети на Opencart 3.0.Теперь ваши к..

Модуль Блог для Opencart 3.0

Модуль Блог для Opencart 3.0

Категория: Модули Opencart

С выходом новой версии Opencart 3.x так и ничего не изменилось в плане встроенных статей - их нет, к..

Модуль SEO Теги PRO для Opencart 3.0

Модуль SEO Теги PRO для Opencart 3.0

Категория: Модули Opencart

Модуль SEO Теги PRO для Opencart 3.0 позволит сделать импорт семантического ядра и получить посадочн..

Вместе дешевле - скидка за комплект Opencart 3.0

Вместе дешевле - скидка за комплект Opencart 3.0

Категория: Модули Opencart

Модуль Вместе дешевле для Opencart 3.0 - позволяет создавать акционные комплекты товаров и назначать..

Оптимизация запросов SQL в opencart

в среднем в корзине клиента 40-45 товаров (специфика магазина) - это создает 6500-6800 SQL запросов.

При любом изменении клиентом количества любой из позиций, опять сыпется 7к запросов.

Уже неоднократно превысили количество запросов в час хоста (750 000).

Нужно оптимизировать, что бы не превышалось количество запросов.

Обновление #1 от 8 октября 2018, 12:17
Опций у товаров нет.

1 день 350 UAH
1 день 350 UAH
Доброго дня
виконаємо якісно
всі розрахунки після обговорення деталей
перегляньте портфоліо
3 дня 450 UAH

3 дня 450 UAH

Я являюсь специалистом компании https://itmarketing.top/ в штате есть программист и верстальщик, который делает проекты на OpenCart.
Стоимость часа работы 450 грн

Мы специально создали сайт, где показаны наши возможности по верстке: http://design.itmarketing.top/
Выберите вариант, который вам больше всего понравился по верстке и по дизайну.

☑ Готовы созваниваться и экономить ваше время на написания сообщений и ТЗ
… ☑ Перед работой пишем подробное ТЗ (бесплатно)
☑ Делаем промежуточные отчеты, чтобы вы знали что происходит с вашим проектом

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *