1C-Битрикс: Управление сайтом

Режим хранения свойств в отдельных таблицах

Введение

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

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

Важным является полная совместимость API. Т.е. техника использования инфоблоков, свойств, элементов и их значений не изменилась. Изменилась методика - например, теперь нет необходимости в дополнительном запросе CIBlockElement::GetProperty при выборе значений свойств функцией CIBlockElement::GetList.

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

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

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

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

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

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

Для свойств инфоблока в административном разделе изменений нет.

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

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

Главные изменения коснулись использования метода GetList. Все они были перечислены во введении.

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

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

Для значений единичных свойств инфоблока с выделенным хранилищем 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 - хранит описание для единичного свойства

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

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

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

<?
//Определяем массив нужных полей элемента
$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"],"<br>";
            //и т.д. и т.п.
        }
    }
}
?>

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

<?
//Определяем массив нужных полей элемента
$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"],"<br>";
            //и т.д. и т.п.
        }
        while ($obElement = $rsElements->GetNextElement())
    }
}
?>

Пользовательские комментарии

Пользовательские комментарии не являются официальной документацией. Ответственность за их использование несет сам пользователь.

Добавлять комментарии могут только зарегистрированные пользователи. Сообщения для просмотра появляются после модерации.
© «Битрикс», 2001-2012, «1C-Битрикс», 2012