Developers/Optimize performance/ru

Использование категории в качестве первого условия
Чем больше товаров в базе данных, тем больше приходится задумываться о построении поисковых запросов и о то, чего желательно избежать! Базы данных имеют ограничения и для некоторых запросов можно не создавать индексов, что ускорит получение результата.

Для получения хорошей производительности необходимо постоянно пытаться по возможности быстрее минимизировать количество фильтруемых записей. Одна из таких возможностей — поиск товаров только в текущей категории. Так как количество товаров в одной категории меньше общего, это быстро уменьшает количество передаваемых фильтру элементов. Используя менеджер индекса каталога сначала добавьте следующее условие поиска:

$search->compare( '==', 'catalog.index.catalog.id', (int) )

Скорость зависит от количества товаров в базе данных, но при наличии 100 000 и более товаров, она будет около 100 мс.

По возможности избегание сортировки
В списках товаров внутри категорий необходимо соблюдать определённый владельцем магазина порядок следования товаров. Это не проблема, так как количество товаров в одной категории обычно укладывается в разумный диапазон. Но при глобальном поиске товаров может произойти большой провал производительности, если заранее не ограничить круг искомых товаров.

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

Нестабильная производительность поиска в списках при использовании критериев из разных доменов
Оптимизатор MySQL постоянно пытается найти лучший индекс для заданного запроса, но его выбор не всегда хорош. Может случиться, что выбран правильный индекс, но используется лишь его часть, даже при доступности гораздо более подходящих частей ключа. Это проблема может случиться при поиске элементов, связанных с товарами.

Попробуйте у себя создать тест производительности по набору данных при помощи

phing setupperf && phing testperf

а затем измените список доменов, из которых должны быть получены данные в lib/mshoplib/tests/Perf/CatalogIndexPerf.php метод testListByPos из

$result = $indexManager->searchItems( $search, array( 'price', 'text', 'media' ), $total );

на

$result = $indexManager->searchItems( $search, array( 'attribute', 'price', 'text', 'media' ), $total );

Вы увидите сильно разнящееся время, необходимое для выполнения запроса. В моём случае разница почти в два раза ввиду необходимости получения дополнительных элементов списка, время для SELECT ... FROM "mshop_product_list" ..., и в три раза по сравнению со временем, когда используется лишь "array( 'price', 'text', 'media' )". Причина проблемы известна, и Пётр Зайцев (Peter Zaitsev) написал статью об этом ещё в 2007, но проблема осталась (по крайней мере в MySQL 5.1). Его решение использования "USE INDEX (...)" в принципе работает, но не может использоваться для запросов в Arcavias, так как они очень сильно зависят от используемых условий. Единственный выход на текущий момент, оставить низким количество доменов в searchItems.

Смотрите также

 * Оптимизация производительности (руководство пользователей)
 * Оптимизация производительности (администраторы)