Дата последнего изменения: 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.