When creating information blocks, infoblock properties should be stored in a separate table, and all property values of each element are stored in the same string. This technique is called Information Blocks 2.0 and permits you to significantly speed up system operation and also to lift a number of restrictions of the previous version of infoblocks. For example, now there is no need to make the additional request CIBlockElement::GetProperty when selecting property values with the function CIBlockElement::GetList.
Note. Documentation to Bitrix Framework, forum messages on the company’s website, and other places may contain the former name of the technique: infoblocks +.
Infoblock 2.0 performance options:
- When selecting elements, property values can be obtained at once, because the number of attached tables in the request is not increased with each property and is always equal to 1.
- Sorting by property values is processed similarly to infoblocks 1.0 (except for multiple properties).
- Selection of multiple property values does not lead to a Cartesian product of a query result; property values are transferred as an array.
- For combined filters by non-multiple (single) properties, now there is an option to create a composite database index manually to speed up sampling operations.
- “Straight through” element sampling is not possible for infoblocks 2.0 when an infoblock type and a symbol code of a property is indicated in the filter. Instead, IBLOCK_ID must be specified in the filter.
Full compatibility with API is important. I.e. the technique for using infoblocks, properties, elements, and their values is the same for both versions of infoblocks.
Storing properties in one common table and managing them using metadata from IBLOCK_PROPERTY_ID. is a very convenient feature for a developer because any metadata can be adjusted at any time without affecting any other information. This drawback is common for regular infoblocks.
If information is stored in infoblocks 2.0 and a property changes its type, e.g. from Number to Line,the storage type in the database itself will also change.
From the point of view of performance, infoblocks 2.0 scores better for small reference tables with a small number (20-30) of rarely changed properties. It makes no sense to shift a newsfeed to this type of infoblocks. You will gain in terms of the number of queries, but lose in terms of the query performance time.
Infoblock 2.0 databases have a physical limit to the number of infoblock properties. At this time, it is not controlled in the system because it depends on a number of unpredictable factors: property types, MySQL configuration, and others. When this physical limit is exceeded, you will obtain a MySQL error that is unusual for Bitrix Framework. However, no data will be lost in this case.
A big advantage of infoblocks 2.0 is the possibility to use composite indexes. However, the situation when sorting is made by = and by several fields simultaneously is quite unusual.
Information Block Level
Information block has a VERSION, attribute that determines whether an information block property value will be stored in a common or an allocated storage when creating a new infoblock. If an allocated storage for a specific infoblock is selected, the database creates two additional tables wherein the names will contain the infoblock indicator. One of the tables will store multiple properties and another one single and cached values of multiple properties.
There is a link to a “converter” between storage types at the editing stage of an infoblock. It should be used with utmost care because the duration of the conversion process depends on the total volume of infoblock property values. Throughout the entire conversion, the infoblock is in an inconsistent state (only a part of values is transferred). In a test configuration for a MySQL version the conversion speed is approximately 1,500 elements per a 20 second step.
The Fetch method is redefined in the CIBlockResult class.The method is responsible for caching values of multiple properties of an element that participate in sampling. For the same properties of the list type, the pairs ID=>VALUE are selected from the reference table.
API provides for a VERSION parameter in the field array $arFields of the method CIBlock::Add. Its values are: 1 – for general storage and 2 – for allocated (new) storage.
Information Block Level of Properties
During the editing of properties (change of a multiplicity attribute or a property type), additional table management operations are performed for the properties stored in the allocated storage, such as delete/add columns, insert/update, or delete a big number of entries. It is best to avoid doing this unless it is absolutely necessary. It is recommended to change the type or multiplicity of one property at a time. Moreover, for single properties, it is recommended to convert them first to multiple properties and then change the type, and the other way around for multiple properties – first comes the type, and then conversion to a single property.
Level of Elements of an Information Block
When adding an element, a relevant entry is made into the table that stores the property values of the element.
Level of Property Values of Information Block Elements
The values of single properties of an infoblock with the allocated ID storage are composite and consist of an element ID and a property ID separated by a colon. When updating multiple properties, the cache of these values resets.
Property values are stored in 2 tables (description of tables and their structure is provided for reference only and is subject to change in later versions):
- b_iblock_element_prop_mNN - for multiple. It has the same structure as b_iblock_element_property;
- b_iblock_element_prop_sNN - for single. It has the field IBLOCK_ELEMENT_ID - infoblock element ID to which the properties:
- PROPERTY_XX - stores values of a single property XX or cache of values for a multiple property;
- DESCRIPTION_XX - stores description for a single property.
How to achieve the best performance using Infoblocks 2.0?
In order to take advantage of the data storage structure used in new infoblocks, component behavior must be modified to a certain extent.
For example: if the code template was more or less like this:
<?
//Determine the array of necessary fields of an element
$arSelect = array(
"ID",
"IBLOCK_ID",
"IBLOCK_SECTION_ID",
"NAME",
"PREVIEW_PICTURE",
"DETAIL_PICTURE",
"DETAIL_PAGE_URL",
);
//Obtain the list of elements. (+1 query)
if($rsElements = GetIBlockElementListEx($IBLOCK_TYPE, false, false, array($ELEMENT_SORT_FIELD => $ELEMENT_SORT_ORDER),
$ELEMENT_COUNT, $arFilter, $arSelect))
{
//Initialization of a page by page display.
$rsElements->NavStart($ELEMENT_COUNT);
$count = intval($rsElements->SelectedRowsCount());
if ($count>0)
{
//For each element:
while ($obElement = $rsElements->GetNextElement())
{
$arElement = $obElement->GetFields();
//Obtain its properties. (+1 query)
$arProperty = $obElement->GetProperties();
//Below property values can be used.
//For example:
echo $arProperty["SOURCE"],"
";
//etc.
}
}
}
?>
Now, after conversion to a new storage type, it is possible to avoid queries in the cycle:
<?
//Determine the array of necessary fields of an element
$arSelect = array(
"ID",
"IBLOCK_ID",
"IBLOCK_SECTION_ID",
"NAME",
"PREVIEW_PICTURE",
"DETAIL_PICTURE",
"DETAIL_PAGE_URL",
"PROPERTY_SOURCE", //Select a property we need
// And all other which may be needed
//directly in the list
);
//Obtain the list of elements. (+1 query)
if($rsElements = GetIBlockElementListEx($IBLOCK_TYPE, false, false, array($ELEMENT_SORT_FIELD => $ELEMENT_SORT_ORDER),
Array("nPageSize"=>$ELEMENT_COUNT), $arFilter, $arSelect))
{
//Initialization of a page by page display.
$rsElements->NavStart($ELEMENT_COUNT);
if($obElement = $rsElements->GetNextElement())
{
//For each element:
do
{
$arElement = $obElement->GetFields();
//Below property values can be used.
//For example:
echo $arElement["PROPERTY_SOURCE"],"
";
//etc.
}
while ($obElement = $rsElements->GetNextElement())
}
}
?>