.
или правильно работать с коллекциями.
Я хочу рассказать вам об ошибках, которые я видел практически в каждом проекте Magento, у которого были проблемы с производительностью.
Работая с Magento, мне иногда приходится проверять чужой код. Поэтому мне хотелось бы поделиться с вами опытом, который поможет улучшить работу ваших сайтов и избежать ошибок в будущем.
Эта статья о Magento 1.*, но описанное применимо и к Magento 2.*.
Практически в каждом проекте, где есть проблемы с производительностью, можно встретить что-то вроде этого:
Неправильный вместо$temp = array(); $collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*'); foreach ($collection as $product) { $product = $product->load($product->getId()); $temp[] = $product->getSku(); }
$temp = array();
$collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('sku');
foreach ($collection as $product) {
$temp[] = $product->getSku();
}
Верно Причины этого очень просты:
- После загрузки нет обязательных атрибутов
- Чем «программисты» занимаются в Интернете
- Загрузка ненужных атрибутов по принципу «хуже не будет»
EAV/Плоские столы ЭАВ – это подход к хранению данных, когда сущность, которой принадлежит атрибут, сам атрибут и его значение разнесены по разным таблицам.
В Magento сущности EAV включают в себя: продукты, категории, клиентов и адреса клиентов.
Сами атрибуты хранятся в таблице eav_attribute. Общие типы значений атрибутов в Magento 5: text, varchar, int, decimal и datetime. Есть еще 1 тип — статический, он отличается от остальных 5 тем, что находится в таблице с сущностью.
Таблица атрибутов указывает, в какой таблице или какого типа находится тот или иной атрибут, а Magento уже знает, куда его записать и откуда прочитать.
Такое хранение значений позволяет достаточно просто реализовать наборы атрибутов (когда каждая сущность может иметь свой атрибут или не иметь его вообще), добавление нового атрибута — это всего лишь еще 1 строка в базе данных.
Добавлено новое значение для 1 атрибута для другого магазина - новая строка в таблице значений этого атрибута.
Как он хранится в базе данных? Сущность: Продукт – каталог_продукт_сущность, Категория – каталог_категория_объект, Клиент – customer_entity, Адрес клиента – customer_address_entity Атрибут: eav_attribute каталог_eav_attribute customer_eav_attribute Ценить: *_текст *_varchar *_int *_десятичная дробь *_datetime Плоский - это всем нам знакомый подход, где все находится в одном месте и нам не нужны никакие дополнительные таблицы, чтобы без лишней работы получить товар и все его атрибуты - SELECT * FROM знак WHERE id = какой-то идентификатор и все.
Из сущностей EAV плоское представление можно использовать только для категорий и продуктов.
Как оно хранится в базе данных? Продукт: каталог_продукт_квартира_1 // *_N просмотр_магазина Категория: каталог_категория_квартира_1 // *_N просмотр_магазина Чтобы включить атрибут в плоскую таблицу и в целом разрешить использование плоских таблиц, необходимо сделать следующее: В админ панели Каталог > Атрибуты > Управление атрибутами.
Magento добавит атрибут в плоскую таблицу, если атрибут имеет одно из следующих значений.
В админ панели Система > Конфигурация > Каталог.
Magento будет использовать плоские таблицы для объектов, перечисленных ниже.
Обратите внимание на следующие факты:
- Плоские таблицы используются ТОЛЬКО на страницах категорий, списке товаров в составе товара Группы, да и вообще везде, где используется коллекция.
Они не используются на странице товара, в админ-панели или при использовании метода загрузки модели.
- После включения Flat-таблиц необходимо провести переиндексацию, иначе Magento продолжит использовать только EAV-таблицы.
- После включения плоских таблиц Magento по-прежнему продолжает использовать EAV, но также начинает копировать изменения в плоскую таблицу при сохранении изменений.
- Производительность Плоский: + Производительность + Для выбора/фильтрации можно применять только существующие атрибуты, добавленные в Плоскую таблицу.
— Ограничение на размер строки (до 65 535 байт, т.е.
85 varchar 255) и количество столбцов (InnoDB до 1000, некоторые до 4096) — Используется только при работе с коллекциями (при загрузке всегда используется EAV) — Результат отличается от выдачи запроса с EAV (без статических атрибутов) — После включения требуется переиндексация, иначе будут использоваться EAV-таблицы — При добавлении нового атрибута необходимо переиндексировать Плоские таблицы.
Кэш Конечно, каждый из вас может мне сказать, зачем нам разбираться, как ускорить запросы в базе данных и как вообще работают коллекции, если нас спасет кэш и все будет кэшироваться.
Отвечу коротко - кэш вас не спасет. Ни один из кешей, предоставляемых в Magento, не кэширует коллекции автоматически и не работает в ваших пользовательских контроллерах и моделях, которые вы используете, скажем, при импорте данных или подсчете чего-либо.
Да к тому же до того, как оно попадет в кэш, потому что его нужно как-то туда поместить и быстро показать пользователю.
Типы кешей в Magento 1.*:
- Конфигурация – кэширует файлы конфигурации
- Макет – кэширует файлы макета
- Блокировать вывод HTML – кэширует шаблоны phtml. По умолчанию он используется во внешнем интерфейсе только в верхнем меню и нижнем колонтитуле.
- Переводы – кэширует файлы перевода csv
- Данные коллекций – кэширует коллекции, использующие метод -> initCache(…).
По умолчанию при инициализации кэшируются только коллекции core_store, core_store_group, core_website.
- Типы и атрибуты EAV – необходимо кэшировать атрибуты eav, НО не кэширует. Используется в 1 методе, который никогда не вызывается, начиная с Magneto CE 1.4.
- Кэш веб-сервисов – кэширует файлы api.xml
- Кэш страниц (FPC) – кэширует весь HTML, кэширует только страницы CMS, категорий, продуктов.
Игнорируется, если протокол https, получить параметр Эno_cache=1, cookie NO_CACHE
- DDL-кэш (Скрытый) – кэширует вызовы DESCRIBE к базе данных, используемые в операциях записи.
и ни один из них не кэширует коллекции автоматически.
Корректная работа с коллекциями Чтобы нагляднее показать, почему что-то нужно делать не так, как многие привыкли, я решил привести несколько тестов производительности разных подходов.
Начнем с испытательного стенда.
Для тестирования я использовал: Испытательный стенд: ОС Икс 10.10 Intel Core i5 3,1 ГГц (4 ядра) 8 ГБ Конфигурация Мадженто: Магенто EE 1.14.0 MySQL 5.5.38 PHP 5.6.2 Содержание: 3 категории 2000 продуктов 2000 страниц CMS Процесс: Для тестов было создано расширение с 1 контроллером и 1 действием, каждый тест проводился 5 раз, затем рассчитывалось среднее время.
Все результаты отображаются в секундах.
class Test_Test_IndexController extends Mage_Core_Controller_Front_Action
{
public function indexAction()
{
$temp = array();
$start = microtime(true);
Init values
Loop start
$temp[] = $product->getSku();
Loop end
Or
Some code snippet
$stop = microtime(true);
echo $stop - $start;
}
}
Псевдокод
Тесты
- EAV/Flat с перезагрузкой модели и без нее
- Кэширование коллекций
- Правильное использование count() и getSize()
- Правильное использование getFirstItem и setPage(1,1)
EAV/Flat с перезагрузкой модели и без нее
Перелистывайте коллекцию.
С загрузкой (перезагрузкой) моделей внутри цикла: $temp = array();
$collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect(.
);
foreach ($collection as $product) {
$product = $product->load($product->getId());
$temp[] = $product->getSku();
}
Перелистывайте коллекцию.
Без загрузки моделей внутри: $temp = array();
$collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect(.
);
foreach ($collection as $product) {
$temp[] = $product->getSku();
}
3 типа выборки данных:
- addAttributeToSelect('*'); // все атрибуты
- addAttributeToSelect('sku'); // 1 статический атрибут
- addAttributeToSelect('имя'); // 1 стандартный атрибут
Как вы наверное заметили, время без перезагрузки моделей НАМНОГО меньше, чем при перезагрузке моделей.
Кроме того, время еще меньше, когда включены плоские таблицы (т.е.
нет лишних объединений и объединений) и мы выбираем только необходимые атрибуты.
В первом случае загружаемся кучей джоинов.
а потом делаем это снова, но уже для модели, и так 2000 раз.
Второй раз мы делаем это для статического атрибута (он находится в той же таблице, что и сам товар) и Magento не нужно делать объединения.
Поэтому времени меньше.
В третий раз Magento необходимо добавить еще одну таблицу, в которой хранится этот атрибут. С плоскими таблицами все аналогично, а в 2 случаях все идентично — это потому, что оба атрибута находятся в 1 таблице, следовательно, время одинаковое.
Я думаю, цифры говорят сами за себя.
Кэширование коллекций
Без кэша: $collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*');
Используя метод initCache:
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->initCache(Mage::app()->getCache(),'our_data',array('SOME_TAGS'));
Пользовательская реализация кэширования:
$cache = Mage::app()->getCache();
$collection = $cache->load('our_data');
if(!collection) {
Теги: #magento #php # Performance #Высокая производительность #php #Разработка электронной коммерции #magento
-
Международная Космическая Станция
19 Oct, 24 -
Ar.drone Прилетел В Москву
19 Oct, 24 -
Студия Лебедева Расторгает Контракт С Nokia.
19 Oct, 24 -
Вконтакте — Клиент Для Iphone Уже В Appstore
19 Oct, 24