323  /  382
Справочник

Как снизить нагрузку с помощью API

Просмотров: 27097
Дата последнего изменения: 15.11.2023
Роберт Басыров
Сложность урока:
3 уровень - средняя сложность. Необходимо внимание и немного подумать.
1
2
3
4
5
Недоступно в лицензиях:
Ограничений нет

Снижаем нагрузку с помощью API

Фильтры по like

Часто встречаемая проблема на проектах это фильтры по 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

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.



23
Курсы разработаны в компании «1С-Битрикс»

Если вы нашли неточность в тексте, непонятное объяснение, пожалуйста, сообщите нам об этом в комментариях.
Развернуть комментарии