Дата последнего изменения: 15.11.2023
Снижаем нагрузку с помощью API |
Часто встречаемая проблема на проектах это фильтры по like
.
Пример в старом API:
<?php // Различные вызовы АПИ и запросы которые они генерируют Bitrix\Main\Loader::includeModule('iblock'); $rs = CIBlockElement::GetList( [], ['CODE' => 'xxx'], // правильно вариант данного фильтра ['=CODE' => 'xxx'], false, false, ['ID', 'CODE', 'NAME'] ); /* SELECT BE.ID as ID,BE.CODE as CODE,BE.NAME as NAME FROM b_iblock B INNER JOIN b_lang L ON B.LID=L.LID INNER JOIN b_iblock_element BE ON BE.IBLOCK_ID = B.ID WHERE 1=1 AND ( ((((BE.CODE LIKE 'xxx'))))) AND (((BE.WF_STATUS_ID=1 AND BE.WF_PARENT_ELEMENT_ID IS NULL)) ) */
Пример в ORM:
<?php Bitrix\Iblock\ElementTable::getList([ 'select' => ['ID', 'NAME', 'CODE'], 'filter' => ['CODE' => 'xxx'] // правильный вариант фильтра 'filter' => ['=CODE' => 'xxx'] ]); /* SELECT `iblock_element`.`ID` AS `ID`, `iblock_element`.`NAME` AS `NAME`, `iblock_element`.`CODE` AS `CODE` FROM `b_iblock_element` `iblock_element` WHERE UPPER(`iblock_element`.`CODE`) like upper('xxx') */
Для ORM есть решение, это
новый фильтр
В обновлении main 17.5.2 в ORM появился новый фильтр.
Подробнее...
.
<?php // С новым фильтром не получится допустить ошибку Bitrix\Iblock\ElementTable::query() ->setSelect(['ID', 'NAME', 'CODE']) ->where('CODE','xxx')->exec(); /* SELECT `iblock_element`.`ID` AS `ID`, `iblock_element`.`NAME` AS `NAME`, `iblock_element`.`CODE` AS `CODE` FROM `b_iblock_element` `iblock_element` WHERE `iblock_element`.`CODE` = 'xxx' */
В старых фильтрах необходимо контролировать like
.
В штатном продукте не предусмотрены все индексы, т.к. все проекты разные. Для улучшения производительности не забывайте предусмотреть создание своих индексов. В этом поможет инструмент
Монитор производительности
Заочно нельзя сказать какие индексы необходимо создавать, надо всегда рассматривать конкретную ситуацию. Индексы нужны для конкретных выборок на конкретных проектах. В зависимости от архитектуры и логики проекта медленные запросы получаются у каждого свои, и для них нужны свои индексы, часто составные.
Страницы Анализ индексов и Список индексов - инструмент анализа и рекомендаций по созданию индексов.
Подробнее в курсе Администратор. Базовый
.
Count
очень тяжелая операция и создает больше нагрузки, чем выборка по запросу.
Проблема очень критична для Rest. Чтобы не использовать Count
в случае если вам не нужно
количество элементов
Например вам нужно просто 10 последних записей.
или вы делаете импорт всех записей по фильтру, передавайте параметр start= -1
. Подробнее почитать об этом и посмотреть пример можно в документации по REST.
Высоконагруженные проекты как правило реализованы с использованием кластера. В кластере есть одна часто встречаемая проблема - срыв конвейера. Конвейер это поток запросов, которые идут последовательно и ядро распределяет их по серверам: на один из слейвов, либо на мастер. Если идет запрос на изменение данных, то конвейер в рамках хита перестает работать и все запросы идут на master, при этом слейвы перестают обслуживать этот хит, оставаясь не занятыми.
Рекомендации по предотвращению срыва конвейера
after_connect*.php
в ядре продукта. Эти файлы содержат настройки подключения к базе данных для случаев, когда мы устанавливаем проект на какой-то хостинг;SET
(в начале хита полностью срывает конвейер);Также могут быть запросы, которые модифицируют данные, но не критично, чтобы изменение было сразу доступно на этом же хите прям со слейва. Тогда такое локальное изменение можно окружить такими методами:
<?php // Выполнение всех запросов на master сервере, без срыва конвейера Bitrix\Main\Application::getInstance()->getConnectionPool()->useMasterOnly(true); // Какие либо обновления и изменения Bitrix\Main\Application::getInstance()->getConnectionPool()->useMasterOnly(false);
Например, таким образом сейчас обернута работа с тегированным кешем.
Вебинар |
Рассмотренную в уроке тему подробнее смотрите в вебинаре:
Мастер-класс по производительности. Highload проекты, как их сделать и поддерживать? Техноволна 6
от 08 апреля 2020.