Оптимізація запитів до інфоблоків 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Оптимізація запитів до інфоблоків 1С-Бітрікс
Середня
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Оптимізація запитів до інфоблоків 1С-Бітрікс

Інфоблок Бітрікс — гнучкий, але важкий інструмент. Таблиці b_iblock_element, b_iblock_element_property, b_iblock_section, b_iblock_element_property_enum утворюють реляційну структуру, яка при необережних запитах породжує жахливі плани виконання. EXPLAIN запиту до списку 100 товарів з 5 властивостями нерідко показує перебір мільйонів рядків і кілька секунд виконання. Для каталогів з активним трафіком це прямо впливає на TTFB та навантаження на MySQL.

Проблеми старого API (CIBlockElement::GetList)

Старий API Бітрікс (CIBlockElement::GetList) при запиті з фільтром PROPERTY_ генерує запит з JOIN до b_iblock_element_property для кожної властивості. При 5 властивостях у фільтрі — 5 JOIN-ів. При цьому API не дозволяє явно керувати планом запиту.

Додаткова проблема — параметр arSelect. Якщо передати "*" або пропустити явний список полів, API запитує всі поля, включаючи об'ємні текстові описи та непотрібні метадані. Для сторінки каталогу з 48 товарами це множить обсяг переданих даних з БД у 3–5 разів.

Перехід на D7 API (Iblock\ElementTable)

API D7 (\Bitrix\Iblock\ElementTable) надає Query Builder з явним контролем select, filter, order, limit. Кожен запит транслюється в SQL і може бути проаналізований через getQuery()->getSql() до виконання.

Приклад оптимального запиту для сторінки каталогу:

use Bitrix\Iblock\ElementTable;

$result = ElementTable::getList([
    'select' => [
        'ID',
        'NAME',
        'CODE',
        'PREVIEW_PICTURE',
        'IBLOCK_SECTION_ID',
    ],
    'filter' => [
        '=IBLOCK_ID'        => CATALOG_IBLOCK_ID,
        '=ACTIVE'           => 'Y',
        '=IBLOCK_SECTION_ID' => $sectionId,
    ],
    'order'  => ['SORT' => 'ASC', 'ID' => 'ASC'],
    'limit'  => 24,
    'offset' => $page * 24,
    'cache'  => ['ttl' => 3600],
]);

Явний select без властивостей — запит лише до b_iblock_element, без JOIN до b_iblock_element_property. Якщо властивості потрібні для частини товарів (наприклад, лише для тих, що потрапили на сторінку), вони запитуються окремим запитом за списком ID — це патерн «запит-по-ID-батчами» замість N+1.

N+1 — головний ворог продуктивності інфоблоку

Проблема N+1 у контексті Бітрікс: отримали список із 24 елементів, а потім для кожного елемента в циклі викликаєте CIBlockElement::GetProperty() або окремий GetList для пов'язаних даних. Підсумок: 1 запит списку + 24 запити властивостей + 24 запити пов'язаних елементів = 49 запитів.

Рішення — пакетна вибірка:

// Отримуємо ID всіх елементів
$ids = array_column($elements, 'ID');

// Один запит для всіх властивостей
$propsResult = \CIBlockElement::GetPropertyValuesArray(
    $ids,
    CATALOG_IBLOCK_ID,
    ['CODE' => ['BRAND', 'COLOR', 'SIZE']]
);

Або через D7 з використанням \Bitrix\Iblock\ElementPropertyTable для вибірки властивостей списком ID.

Кешування на рівні компонентів vs на рівні даних

Кеш компонента (файловий, через initCache) — грубий інструмент: кешується весь HTML-фрагмент, інвалідується за тегом IBLOCK_N. Для сторінок з персоналізацією або частими оновленнями каталогу це незручно.

Кешування на рівні даних через ManagedCache з гранулярними тегами (по розділу, по набору властивостей) дозволяє інвалідувати лише зачеплені записи. Витрати — необхідність явно прописувати кеш у кожному місці звернення до даних.

Кейс: каталог будматеріалів, 45 000 SKU

До оптимізації: сторінка розділу каталогу (48 товарів) — 1,8 с TTFB (без кешу), 340 мс з кешем. MySQL slow query log показував: один запит до списку товарів — 640 мс, другий запит «схожих товарів» — 310 мс, сумарно 12 запитів на сторінку.

Виявлені проблеми:

  • CIBlockElement::GetList з SELECT => "*" і PROPERTY_FILTER => [5 властивостей]
  • N+1 у блоці «схожі товари»: запит до кожного з 6 товарів окремо
  • Запит розділу з повним деревом дочірніх розділів без обмеження рівня

Що зробили:

  • Переписали основний запит на D7, explicit select (8 полів замість усіх)
  • Пакетний запит властивостей для блоку «схожі товари»
  • Обмеження дерева розділів через параметр DEPTH_LEVEL і кеш з тегом розділу
  • Додавання індексів на b_iblock_element: складений по (IBLOCK_ID, IBLOCK_SECTION_ID, ACTIVE, SORT)

Результат: сторінка розділу (без кешу) — 380 мс TTFB, з кешем — 45 мс. Кількість запитів до БД: 12 → 4. Навантаження на MySQL знизилося, з'явилася можливість обслуговувати в 3 рази більше одночасних користувачів без додавання потужностей.

Складені індекси для інфоблоків

Стандартні індекси Бітрікс не покривають усі типові вибірки. Критичний індекс для каталогу:

ALTER TABLE b_iblock_element
  ADD INDEX idx_iblock_section_active_sort
    (IBLOCK_ID, IBLOCK_SECTION_ID, ACTIVE, SORT);

Аналіз поточних індексів через SHOW INDEX FROM b_iblock_element і EXPLAIN конкретних запитів зі slow log — обов'язковий крок перед додаванням.

Терміни

Етап Термін
Аудит запитів (slow log, Explain, панель Бітрікс) 1–2 дні
Переробка критичних запитів (D7, batching) 3–7 днів
Індекси та налаштування кешу 1–2 дні

На великих проєктах з великою кількістю кастомних компонентів — до 3 тижнів.