Как повысить производительность Magento
Как повысить производительность Magento
В этой статье я расскажу о типичных ошибках, которые я наблюдал почти в каждом проекте Magento с низкой производительностью. Работая с Magento, мне иногда приходится проводить аудит чьего-то кода. Вот почему я хотел бы поделиться своим опытом и помочь вам повысить производительность Magento и избежать ошибок в будущем.
* В этой статье вы найдете информацию о Magento 1, однако следующие советы применимы и для Magento 2.
Практически каждый проект на основе Magento с низкой производительностью содержит следующее:
Неверно
Вместо того:
Верный
Причины этого просты:
- После загрузки нет необходимых атрибутов.
- То же самое и с «разработчиками» в Интернете.
- Скачивание дополнительных атрибутов по принципу «хуже не бывает».
Чтобы объяснить, как повысить продуктивность, я хотел бы выделить следующие вопросы:
- EAV и плоские столы
- Кеш
- Как работать с коллекциями.
EAV / Плоские столы
EAV – это подход к хранению данных, когда объект, на который ссылается атрибут, сам атрибут и его значение разделены в разных таблицах.
В Magento объекты EAV включают: продукты, категории, клиентов и их адреса. Атрибуты хранятся в таблицах eav_attribute .
В Magento есть четыре типа значений атрибутов: текст, varchar, int, decimal и datetime. Пятый тип, который называется статическим, – это сохранение в таблице сущностей. В таблице атрибутов указывается, в какой таблице или к какому типу принадлежит атрибут, и таким образом Magento «знает», откуда его читать и куда писать.
Такое хранилище значений позволяет просто реализовать наборы атрибутов (где каждая сущность может иметь свой собственный атрибут или не иметь его вообще); добавление нового атрибута означает новую строку в базе данных.
Как хранится в БД:
Flat – это распространенный подход, когда все хранится в одном месте и не нужны дополнительные таблицы. Чтобы получить элемент и все атрибуты, введите: SELECT – FROM table
WHERE id = some id
Из сущностей EAV, Flat применимы только для категорий и элементов.
Как хранится в БД:
Чтобы включить атрибут в плоскую таблицу и обычно включить плоские таблицы, введите следующее:
Плюсы и минусы EAV и Flat столов:
EAV:
+ более гибкий
+ нет необходимости повторно индексировать данные при добавлении нового атрибута
+ почти неограниченное количество атрибутов
+ доступность всех атрибутов
+ наличие статических атрибутов (sku, created_at, updated_at), даже если они специально не указаны
– Неустранимая ошибка: вызов к функции-члену получить Back end() при выборе / фильтрации несуществующего атрибута
– Производительность.
Квартира:
+ Производительность
+ Можно выбрать / отфильтровать только существующие атрибуты, которые добавлены в плоскую таблицу
– Ограничение размера строки (65 535 байтов или 85 varchar 255) и количества столбцов (1000 для InnoDB )
– Используется только для коллекций
– Результат отличается от ответа в запрос EAV (без статических атрибутов)
–
требуется повторная индексация, иначе будут использоваться таблицы EAV – Добавление нового атрибута требует повторной индексации плоской таблицы
Кеш
Многие из вас могут сказать, что нет необходимости выяснять, как ускорить запросы к БД и вообще как работают коллекции, потому что кеш решит все проблемы. Вкратце, кеш тут ни при чем. Ни один из типов кешей Magento не может автоматически кэшировать коллекции, а также работать в ваших пользовательских контроллерах и моделях, которые вы используете, например, при импорте данных.
Типы кеша в Magento:
-
Конфигурация – кэширует файлы конфигурации
-
Макет – кеширует файлы макета
-
Блокировать вывод HTML – кеширует шаблоны phtml. По умолчанию он используется только во внешнем интерфейсе в верхнем меню или нижнем колонтитуле.
-
Переводы – кеши переводят файлы csv
-
Данные коллекций – кэширует коллекции, которые используют -> initCache (…) По умолчанию при инициализации кэшируются только коллекции core_store, core_store_group, core_website .
-
Типы и атрибуты EAV – должны кэшировать атрибуты eav, но не кэшировать.
-
Кэш веб-сервисов – кеширует файлы api.xml
-
Кэш страницы (FPC) – кэширует только весь HTML или CMS, страницы категорий и продуктов. Игнорируется для протокола https, получить вариант? No_cache = 1 файл cookie NO_CACHE
-
DDL Cache (Hidden) – кеширует запросы DESCRIBE к базе данных; используется для записи транзакций
Как работать с коллекциями
Чтобы показать, почему необходимо выполнять одни действия не так, как привыкли другие, я решил провести несколько тестов производительности разных подходов. Начнем со стенда:
Стенд:
OS X 10.10
3,1 ГГц Intel Core i5 (4 ядра)
8 ГБ
Конфигурация Magento:
Magento EE 1.14.0
MySQL 5.5.38
PHP 5.6.2
Содержание:
3 категории
2000 товаров
2000 страниц CMS
Процесс:
Я создал расширение с одним контроллером и одним действием. Каждый тест проводился 5 раз, а затем подсчитывалось среднее время. Все результаты даны в секундах.
Тесты
- EAV / Flat с загрузкой моделей и без нее
- Кеширование коллекций
- Правильное использование count () и getSize ()
- Правильное использование getFirstItem и setPage (1,1)
С загрузкой моделей в цикле
Без загрузки моделей в цикле
3 типа выделения:
1. addAttributeToSelect (‘*’); // Все атрибуты
2. addAttributeToSelect (‘sku’); // 1 статический атрибут
3. addAttributeToSelect (‘name’); // 1 стандартный атрибут
Результат
Как вы, наверное, заметили, время без загрузки моделей намного меньше, чем с загрузкой моделей. Также время меньше, когда включены плоские таблицы (без лишних объединений и объединений) и мы выбираем необходимые атрибуты.
К тому же,
в первом случае мы выполняем загрузку с помощью кучи соединений, а затем снова делаем это для модели… а затем снова и снова. Во втором случае мы делаем это для статического атрибута (он хранится в той же таблице, что и товар), и Magento не должен выполнять соединения. Вот почему нужно меньше времени. В третьем случае Magento должен присоединиться к таблице, в которой хранится атрибут.
Аналогично для плоских таблиц: в двух случаях цифры одинаковы, потому что оба атрибута хранятся в одной таблице и, следовательно, время одинаковое.
- Кеширование коллекций
Без кеша
Используя метод initCache:
Пользовательский кеш
Я предлагаю проверить выделение без кеширования, с помощью метода, предлагаемого Magento,
и обходного пути, которого я больше нигде не наблюдал. Я сам это придумал на основе методов модели кеша.
Результат
Выбор без кеша очевиден. Напротив, метод Magento увеличил время, что лично меня удивило. Кэш EAV вообще не был хорошей идеей, так как коллекция EAV сначала загружает сущности из таблиц продуктов (то есть то, что кэшируется), а затем отдельным запросом выбирает значения атрибутов и заполняет объекты. В коллекции Flat все выбирается из одной таблицы.
Тем не менее,
на работу с кешем нужно больше времени, чем с БД. InitCache означает, что сначала он собирает все данные (разбиение на страницы, фильтры, события и т.д.) В саму коллекцию, создает хэш из запроса sql, который затем будет искать в кеше; если он там что-то найдет, то проанализирует и после всех событий запустится и другие дальнейшие методы. Это самая медленная процедура во всем процессе, и это показывает, что кеш работает намного медленнее, чем простой запрос в БД.
В заключение,
Хочу пояснить изобретенный мною метод, который подразумевает кеширование конечного результата сбора, а главное – исключение всех событий и дополнительной загрузки атрибутов.
• Правильное использование count () и getSize ()
getSize ()
счет ()
Результат
Разница между методами заключается в следующем: count () загружает все объекты коллекции, а затем с помощью php count подсчитывает количество объектов и выдает нам цифру.
GetSize () не загружает коллекцию и генерирует еще один запрос в БД, где нет ограничений, порядков и списков выбранных атрибутов. Есть только COUNT *.
Как узнать, какой метод использовать?
Если вам нужно знать, находятся ли значения в БД и сколько их, используйте getSize (). Если вам нужна уже загруженная коллекция, используйте count () – он выдаст вам количество элементов, которые уже загружены в коллекцию.
• Правильное использование getFirstItem и setPage (1,1)
getFirstItem ()
setPage (1,1)
load ()
Результат
Недостатком getFirstItem является то, что он загружает всю коллекцию, а затем возвращает первый элемент в foreach; если его нет, он возвращает пустой элемент.
setPage (он же $ this-> setCurPage ($ pageNum) -> setPageSize ($ pageSize)) ограничивает выбор только одной записью, что, как видите, ускоряет загрузку результата.
Даже загрузка выполняется быстрее, чем getFirstItem, однако загрузка намного медленнее, чем выбор одноэлементной коллекции. Причина в том, что загрузка всегда работает с таблицами EAV.
Подводить итоги,
Хочу дать несколько советов тем, кто работает с Magento:
• Никогда не вызывайте метод загрузки для объектов, производных от коллекции
• Загружайте только необходимые атрибуты
• Используйте плоскую таблицу, если применимо для проекта
• Используйте count для подсчета результатов загруженной коллекции и getSize для получения количества всех записей
• Не используйте GetFirstItem без setPage (1,1) или аналогичные методы.
Источник записи: https://elogic.co