132  /  330

Инфоблоки 2.0

Просмотров: 6578 (Статистика ведётся с 06.02.2017)

При создании информационных блоков рекомендуется хранить свойства инфоблока в отдельной таблице, причем все значения свойств одного элемента хранятся в одной строке. Эта технология называется Инфоблоки 2.0 и позволяет существенно ускорить работу системы, а также снять ряд ограничений в предыдущей версии инфоблоков. Например, теперь нет необходимости в дополнительном запросе CIBlockElement::GetProperty при выборе значений свойств функцией CIBlockElement::GetList.

Примечание. В документации к Bitrix Framework, в сообщениях форума на сайте компании и в других местах могут встречаться прежние названия технологии: инфоблоки +.

Возможности инфоблоков 2.0:

  • При выборке элементов можно сразу получать значения свойств, т.к. количество присоединяемых таблиц в запросе не увеличивается с каждым свойством, а всегда равно единице.
  • Фильтрация по значениям свойств происходит аналогично инфоблокам 1.0 (за исключением множественных).
  • Выборка значений множественных свойств не приводит к декартовому произведению результата запроса - значения свойств передаются в виде массива.
  • Для комбинированных фильтров по немножественным (единичным) свойствам появилась возможность ручного создания составных индексов БД для ускорения операций выборки.
  • Для инфоблоков 2.0 нет возможности "сквозной" выборки элементов, когда в фильтре указывается тип инфоблока и символьный код свойства. В фильтре необходимо указывать IBLOCK_ID.
  • В инфоблоках 2.0 таблица со связанными элементами будет присоединяться (join) только один раз.

Важным является полная совместимость API. То есть техника использования инфоблоков, свойств, элементов и их значений одинакова для обоих версий инфоблоков.

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

Если информация хранится в инфоблоках 2.0 и у свойства меняется его тип (например, с Числа на Строку), то изменяется и тип хранения в самой базе данных. То есть меняется не логика интерпретации продуктом значения этого свойства, а меняется само значение. То есть нельзя "играться" с данными.

С точки зрения производительности инфоблоки 2.0 выигрывают на небольших справочниках с небольшим количеством (20-30) редко изменяемых свойств. Ленту новостей нет никакого смысла переводить на этот вид инфоблоков. Вы выиграете в числе запросов, но проиграете во времени их исполнения.

В инфоблоках 2.0 существует физическое ограничение БД на количество свойств инфоблока. На данный момент это не отслеживается в системе, так как зависит от множества непрогнозируемых факторов: типа свойств, конфигурации MySQL и других. При превышении этого физического ограничения вы получите редкую для Bitrix Framework ошибку MySQL. Данные при этом потеряны не будут.

Внимание! Перевод из обычных инфоблоков в инфоблоки 2.0 невозможен при числе свойств более 50.

Большое преимущество инфоблоков 2.0 – возможность использования составных индексов. Однако ситуация, когда выполняется фильтр по = и по нескольким полям одновременно – ситуация достаточно редкая.

Уровень информационного блока.

У информационного блока есть признак VERSION, который при создании нового инфоблока определяет выбор хранения значений свойств информационного блока в общем хранилище или в выделенном. При выборе выделенного хранения для данного инфоблока в БД создаются две дополнительные таблицы, включающие в своё имя идентификатор инфоблока. В одной из них будут храниться множественные свойства, а в другой единичные и кешированные значения множественных.

При редактировании инфоблока доступна ссылка на "конвертер" между типами хранения. Пользоваться им надо с большой осторожностью, т.к. продолжительность процесса конвертации зависит от общего объема значений свойств инфоблока. В течение всего процесса инфоблок находится в несогласованном состоянии (часть значений перенесена, а часть нет). На тестовой конфигурации для MySQL версии скорость была порядка 1500 элементов за 20-ти секундный шаг.

В классе CIBlockResult переопределён метод Fetch. В нем происходит кеширование значений множественных свойств элемента, участвующих в выборке. Для этих же свойств типа список выбираются пары ID=>VALUE из справочника списков.

В API предусмотрен параметр VERSION в массиве полей $arFields метода CIBlock::Add. Его значения: 1 - для общего хранения и 2 - для выделенного (нового).

Уровень свойств информационного блока

При редактировании свойств (смена признака множественности или типа свойства) для свойств в выделенном хранилище выполняются дополнительные операции по управлению таблицами. Такие как удаление/добавление колонок, вставка/обновление или удаление большого количества записей. Без настоятельной необходимости лучше избегать этого. Наилучшей методикой будет менять тип или множественность одного свойства за один раз. Причем для единичных свойств предпочтительнее сначала сделать его множественным а потом сменить тип, а для множественных наоборот - сначала тип, и уже потом делать его единичным.

Уровень элементов информационного блока

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

Уровень значений свойств элементов информационного блока

Значения единичных свойств инфоблока с выделенным хранилищем ID - составные и состоят из ID элемента и ID свойства, разделенных двоеточием. При обновлении множественных свойств происходит сброс кеша этих значений.

Значения свойств хранятся в 2-х таблицах (описание таблиц и их структуры имеет справочный характер и могут меняться в следующих версиях):

  • b_iblock_element_prop_mNN - для множественных. Имеет ту же самую структуру, что и b_iblock_element_property;
  • b_iblock_element_prop_sNN - для единичных. Имеет поле IBLOCK_ELEMENT_ID - ID элемента инфоблока которому принадлежат свойства:
    • PROPERTY_XX - хранит значения единичного свойства XX или кеш значений для множественного свойства;
    • DESCRIPTION_XX - хранит описание для единичного свойства.

Как достичь наибольшей эффективности при использовании Инфоблоков 2.0?

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

Например: если раньше шаблон кода был примерно таким:

<?
//Определяем массив нужных полей элемента
$arSelect = array(
    "ID",
    "IBLOCK_ID",
    "IBLOCK_SECTION_ID",
    "NAME",
    "PREVIEW_PICTURE",
    "DETAIL_PICTURE",
    "DETAIL_PAGE_URL",
);
//Получаем список элементов. (+1 запрос)
if($rsElements = GetIBlockElementListEx($IBLOCK_TYPE, false, false, array($ELEMENT_SORT_FIELD => $ELEMENT_SORT_ORDER), 
$ELEMENT_COUNT, $arFilter, $arSelect))
{
    //Инициализация постраничного вывода.
    $rsElements->NavStart($ELEMENT_COUNT);
    $count = intval($rsElements->SelectedRowsCount());
    if ($count>0)
    {
        //Для каждого элемента:
        while ($obElement = $rsElements->GetNextElement())
        {
            $arElement = $obElement->GetFields();
            //Получаем его свойства. (+1 запрос)
            $arProperty = $obElement->GetProperties();
            //Ниже можно пользоваться значениями свойств.
            //Например:
            echo $arProperty["SOURCE"],"
"; //и т.д. и т.п. } } } ?>

Теперь, после преобразования в новый тип хранения, стало возможным избавится от запросов в цикле:

<?
//Определяем массив нужных полей элемента
$arSelect = array(
    "ID",
    "IBLOCK_ID",
    "IBLOCK_SECTION_ID",
    "NAME",
    "PREVIEW_PICTURE",
    "DETAIL_PICTURE",
    "DETAIL_PAGE_URL",
    "PROPERTY_SOURCE", //Выбираем нужное нам свойство
    // И все другие какие могут понадобится
    // непосредственно в списке
);
//Получаем список элементов. (+1 запрос)
if($rsElements = GetIBlockElementListEx($IBLOCK_TYPE, false, false, array($ELEMENT_SORT_FIELD => $ELEMENT_SORT_ORDER), 
Array("nPageSize"=>$ELEMENT_COUNT), $arFilter, $arSelect))
{
    //Инициализация постраничного вывода.
    $rsElements->NavStart($ELEMENT_COUNT);
    if($obElement = $rsElements->GetNextElement())
    {
        //Для каждого элемента:
        do
        {
            $arElement = $obElement->GetFields();
            //Ниже можно пользоваться значениями свойств.
            //Например:
            echo $arElement["PROPERTY_SOURCE"],"
"; //и т.д. и т.п. } while ($obElement = $rsElements->GetNextElement()) } } ?>
36
Курсы разработаны в компании «1С-Битрикс»

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