Часто возникают вопросы производительности проектов на базе "1С-Битрикс", для решения которых нет необходимости прибегать к "экстремальным методам". Чтобы, помочь в решении таких проблем, особенно разработчикам только начинающим работать с "1С-Битрикс", рассмотрим пример оптимизации "некой" страницы информационного сайта. Для этого будем использовать только встроенный в продукт инструментарий.
И так, что мы имеем:
Фильтр топ новостей:
Фильтр обычных новостей
Стартовое время выполнения страницы:
топ новости php: 0,0285с. - sql: 0,0085с.
новости php: 6,144с. - sql: 6,0927с.
Смотрим какой запрос генерирует основную нагрузку, копируем его в SQL консоль выполняя EXPLAIN.
Видим, что в выбоке из таблицы b_iblock_element задействованно очень много строк. При этом используемый индекс ix_iblock_element_code в данном случае не эффективен. Проанализировав запрос приходим к выводу что основная проблема в данном случае из за проверки периода активности у элемента
В запросе же с выборкой топ новостей проблемы не возникает, из за высокой селективности выборки по свойству MAIN_NEWS. И индексу по числовому свойству в таблице b_iblock_element_property.
Чтобы решить данную проблему делаем следующее:
топ новости php: 0,0188с. - sql: 0,0029с.
новости php: 0,0475с. - sql: 0,0243с.
как видим мы достаточно легко получили хороший результат.
Предположим, что по ряду причин используются инфоблоки+, как же будут выглядеть время генерации страницы? Конвертируем инфоблок и смотрим время выполнения:
топ новости php: 6,9868с. - sql: 6,9709с.
новости php: 0,2191с. - sql: 0,1942с.
Также смотрим в SQL консоли explain для самого тяжелого запроса из топ новостей и видим аналогичную проблему, только теперь виной тому отсутствие индекса по свойству MAIN_NEWS. (В первых инфоблоках по числовым значениям строится индекс)
Добавляем индекс
И смотрим результат
Как видим и в данном случае добились хорошей производительности.
В качестве итога
Добавлять индексы по дате активности в b_iblock_element надо осторожно. Может быть ситуация в которой данный индекс будет не желательно использовать. В этом случае можно дату начала и окончания активности в виде timestamp продублировать в виде числовых свойств инфоблока и фильтровать по ним.
При добавление своих индексов надо создавать заведомо уникальное имя, чтобы не возникла ситуация при которой может совпасть имя созданного вами индекса и индекса который может быть добавлен через систему обновлений.
В первых инфоблоках уже есть индекс на все числовые свойства, и ID значений свойств списков. Если же вы используете инфоблоки+ то вам надо в ручную проставить индексы на те свойства по которым у вас будет осуществляться выборка
В дальнейшем постараюсь затронуть и другие моменты оптимизации.
И так, что мы имеем:
- VMBitrix (512M памяти)
- инфоблок новостей ~12600, в каждой новости заполнен анонс, детальная информация, название, теги и ряд свойств
- страница с 2-мя компонентами news.list, которые выводят два блока новостей (топ 0 - 10 шт и обычные - 10 шт).
- топ новости, не должны попадать в обычные
- разделение на топ и обычные новости происходит при помощи числового свойства MAIN_NEWS
- при выводе новостей проверяется период активности, ежедневно добавляется 5 - 10 новостей
- тяжёлая фильтрация по дате активности
- кэширование в период максимальной нагрузки не может полностью закрыть проблему производительности. Так как, обычно в этот же момент происходит довольно частый сброс кэша, после добавления новостей, их изменения или при других событиях (добавление комментариев, оценок и.т.д.). Поэтому необходимо добиться быстрой генерации страницы без использования кэширования.
Фильтр топ новостей:
$arTop = array('PROPERTY_MAIN_NEWS' => 100); |
$arNews = array('!PROPERTY_MAIN_NEWS' => 100); |
топ новости php: 0,0285с. - sql: 0,0085с.
новости php: 6,144с. - sql: 6,0927с.
Смотрим какой запрос генерирует основную нагрузку, копируем его в SQL консоль выполняя EXPLAIN.
Видим, что в выбоке из таблицы b_iblock_element задействованно очень много строк. При этом используемый индекс ix_iblock_element_code в данном случае не эффективен. Проанализировав запрос приходим к выводу что основная проблема в данном случае из за проверки периода активности у элемента
(((BE.ACTIVE_TO >= now() OR BE.ACTIVE_TO IS NULL) AND (BE.ACTIVE_FROM <= now() OR BE.ACTIVE_FROM IS NULL))) |
Чтобы решить данную проблему делаем следующее:
- добавляем в фильтр ограничение по времени начала активности '>DATE_ACTIVE_FROM' => ConvertTimeStamp(time() - 2592000), т.к. новости публикуются каждый день и у нас достаточно большой их объем, ограничиваем выборку неким периодом (неделя, месяц)
- добавляем в таблицу b_iblock_element индекс
ALTER TABLE b_iblock_element ADD INDEX `ix_custom_iblock_news_date` (`ACTIVE_FROM`,`ACTIVE_TO`);
топ новости php: 0,0188с. - sql: 0,0029с.
новости php: 0,0475с. - sql: 0,0243с.
как видим мы достаточно легко получили хороший результат.
Предположим, что по ряду причин используются инфоблоки+, как же будут выглядеть время генерации страницы? Конвертируем инфоблок и смотрим время выполнения:
топ новости php: 6,9868с. - sql: 6,9709с.
новости php: 0,2191с. - sql: 0,1942с.
Также смотрим в SQL консоли explain для самого тяжелого запроса из топ новостей и видим аналогичную проблему, только теперь виной тому отсутствие индекса по свойству MAIN_NEWS. (В первых инфоблоках по числовым значениям строится индекс)
Добавляем индекс
ALTER TABLE b_iblock_element_prop_s33 ADD INDEX `ix_cust_prop155` (`PROPERTY_155`); |
И смотрим результат
Как видим и в данном случае добились хорошей производительности.
В качестве итога
Добавлять индексы по дате активности в b_iblock_element надо осторожно. Может быть ситуация в которой данный индекс будет не желательно использовать. В этом случае можно дату начала и окончания активности в виде timestamp продублировать в виде числовых свойств инфоблока и фильтровать по ним.
При добавление своих индексов надо создавать заведомо уникальное имя, чтобы не возникла ситуация при которой может совпасть имя созданного вами индекса и индекса который может быть добавлен через систему обновлений.
В первых инфоблоках уже есть индекс на все числовые свойства, и ID значений свойств списков. Если же вы используете инфоблоки+ то вам надо в ручную проставить индексы на те свойства по которым у вас будет осуществляться выборка
В дальнейшем постараюсь затронуть и другие моменты оптимизации.