Что лучше — один большой или много маленьких запросов SQL?
Есть инфоблок, в нем ок. 300 разделов. Нужно вытащить из инфоблока все разделы и кол-во элементов у них. Есть 2 способа:
1) Одним запросом через CIblockSection, с указанием ELEMENT_CNT
2) Один запрос CIblockElement без ELEMENT_CNT и на каждый раздел делать CIblockElement::GetList()->SelectedRowsCount()
Первый способ выполняется за 1,2 сек.
Второй за 0,7 сек.
Выходит, что второй запрос быстрее. Но всегда ли это так?
Вызов метода у CIblockSection один раз не равно одному запросу в бд. (по крайней мере не всегда, в данном случае так точно не равно).
Так же как и количество запросов не показатель.
Если задаётесь вопросом производительности запросов, надо смотреть реальные запросы в бд и время их выполнения.
Что там происходит под капотом при передаче ELEMENT_CNT наверное одному богу известно)
Вот например чистый запрос под вашу задачу) 1304 раздела, 40к товаров. Отрабатывает за ~120ms
Единственное, он не учитывает множественные привязки к разделам)
select b_iblock_section.*,
(select count(*)
from b_iblock_element
where b_iblock_element.IBLOCK_ID = 1 &&
b_iblock_element.IBLOCK_SECTION_ID = b_iblock_section.ID) as element_count
from b_iblock_section
where b_iblock_section.IBLOCK_ID = 1
Но вы так не делайте, а то а-та-та)
При работе с компонентами не надо обращаться к базе напрямую. Концепция работы с продуктом предполагает работу с данными через функции API. Структура данных может меняться от версии к версии, а функции сохраняют обратную совместимость. Мы настоятельно не рекомендуем использовать прямые запросы к БД, т.к. это может нарушить целостность данных и привести к неработоспособности сайта. В силу вышесказанного структура таблиц не афишируется.
Запросы к реляционной базе данных в цикле "зло"!
Когда занимался глубокой оптимизацией битрикс на 200к товаров и больше 1000 свойств, все такие перлы пришлось убирать.
В вашем случае сразу получать ID разделов элементов с группировкой, чтобы не лезть прямыми запросами в базу, используйте D7, там есть querybuilder