Перейти к содержимому

Где хранить данные - инфоблок, highload-блок или своя таблица

Выбираем хранилище под задачу: инфоблок с готовым интерфейсом, highload-блок для больших справочников и своя таблица для собственной структуры данных.

Что нужно знать заранее

Инфоблок даёт готовый интерфейс, права и поиск, но платит за это структурой хранения свойств. На небольших объёмах это незаметно, а на сотнях тысяч записей разница в скорости становится решающей.

Highload-блок задуман под большие справочники с простой структурой полей. У него нет прав на отдельные записи и нет привычного интерфейса редактора, зато выборки работают быстро и предсказуемо.

Своя таблица даёт полную свободу и полную ответственность. Интерфейс, права, кэширование и миграции структуры придётся написать самому, зато схема данных будет ровно такой, какая нужна проекту.

Шаги

  1. Выяснить, кто ведёт данные: редактор в админке, обмен из учётной системы или код.
  2. Оценить объём записей и частоту их изменения на горизонте пары лет работы.
  3. Проверить, нужны ли права на отдельные записи и штатный поиск по содержимому.
  4. Выбрать хранилище по этим ответам, а не по привычке команды разработчиков.
  5. Заложить в оценку стоимость переезда, если требования могут заметно измениться.

Решение

Считаем текущие объёмы данных проекта:

SELECT 'элементы', COUNT(*) FROM b_iblock_element
UNION ALL SELECT 'значения свойств', COUNT(*) FROM b_iblock_element_property;
-- значений свойств обычно в разы больше самих элементов, и это главная цена инфоблока

Число значений свойств отвечает на вопрос о цене хранения лучше любых советов. Каталог на десять тысяч товаров с двадцатью свойствами - это уже двести тысяч строк в таблице значений.

Заводим справочник в highload-блоке:

$result = \Bitrix\Highloadblock\HighloadBlockTable::add([
'NAME' => 'VendorCity', // имя класса сущности, с большой буквы
'TABLE_NAME' => 'vendor_city', // имя таблицы в базе данных
]);
// поля справочника добавляют пользовательскими полями к созданной сущности

Highload-блок хорош ровно там, где нужен большой плоский справочник. Города, пункты выдачи, коды скидок и совместимость запчастей ложатся на него отлично, а дерево разделов - уже нет.

Заводим свою таблицу под собственную структуру:

class VendorContractTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName(): string { return 'vendor_contract'; }
public static function getMap(): array
{
return [
(new \Bitrix\Main\ORM\Fields\IntegerField('ID'))->configurePrimary(true)->configureAutocomplete(true),
(new \Bitrix\Main\ORM\Fields\StringField('NUMBER'))->configureRequired(true),
new \Bitrix\Main\ORM\Fields\DatetimeField('SIGNED_AT'),
];
}
}

Своя таблица выигрывает там, где важны собственные индексы и предсказуемый запрос. Договоры, журналы обмена и служебные очереди почти всегда живут именно так, а не в инфоблоках.

Сравниваем скорость выборки на своих данных:

$start = microtime(true);
\Bitrix\Iblock\Elements\ElementCatalogTable::getList(['limit' => 500])->fetchAll();
printf("инфоблок: %.3f c\n", microtime(true) - $start);
// тот же замер повторяют для highload-блока и для своей таблицы на боевых объёмах

Планируем переезд заранее:

// прикладной код обращается к репозиторию, а не к конкретному хранилищу
interface CityRepository { public function findByCode(string $code): ?array; }
// при смене хранилища меняется одна реализация, а не весь проект

Прослойка репозитория делает переезд возможным без переписывания половины проекта. Она же помогает при переходе с инфоблоков на своё хранилище, когда каталог перерастает исходное решение.

Типичные проблемы

Каталог из сотен тысяч записей стал медленным.

Данные лежат в инфоблоке со множеством свойств, и выборка собирает их по частям. Плоские справочники переносят в highload-блок или в свою таблицу.

Редактор не может вести справочник сам.

Данные лежат в своей таблице, интерфейс к которой никто не написал. Для данных, которые ведёт человек, берут инфоблок или универсальный список.

Права на отдельные записи не работают.

Выбран highload-блок, а он прав на записи не поддерживает совсем. Такие требования закрывают инфоблоком или проверками в своём коде.

Поиск по сайту не находит данные.

Своя таблица и highload-блок в поисковый индекс сами не попадают. Их индексацию пишут своим кодом либо переносят данные в инфоблок.

Переезд на другое хранилище встал в месяцы.

Прикладной код обращался к хранилищу напрямую из десятков мест. Обращения прячут за одним классом доступа с первого дня проекта.

Частые вопросы

Когда инфоблок точно лучше?

Когда данные ведёт редактор и нужны права, поиск и привычный интерфейс. Новости, статьи, страницы и обычный каталог живут в инфоблоках без вопросов.

Highload-блок быстрее инфоблока?

На плоских справочниках заметно быстрее, потому что данные лежат в одной таблице. На данных со сложной структурой разница уже не так велика.

Можно ли смешивать хранилища в одном проекте?

Да, и это нормальная практика: каталог в инфоблоке, справочники в highload-блоке, журналы в своей таблице. Главное - не размазывать одну сущность по двум хранилищам.

Что выбрать для журналов и очередей?

Свою таблицу с нужными индексами и своей чисткой по сроку. Инфоблок для такого не предназначен и быстро разрастается.

Как понять, что пора переезжать?

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

Смежное

Первоисточник