@TechNOIR

1С-Битрикс. Как массово и достаточно быстро удалить все разделы в инфоблоке?

Добрый день!
Подскажите пожалуйста как массово и достаточно быстро удалить все разделы в инфоблоке?
Всего разделов 55к
Через админку всё виснет, несмотря на больше max execution time.

Скрипт такой набросал, но как-то долговато работает.. Или это норма?

Спасибо заранее

<?php
set_time_limit(60000);
// включаем вывод ошибочек
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// включаем замер исполнения скрипта

// подключаем prolog bitrix 
require $_SERVER["DOCUMENT_ROOT"] . '/bitrix/modules/main/include/prolog_before.php';
// подключаем нужные модули
CModule::IncludeModule("iblock");
$infoblock = 4; // Инфоблок с ID ХХХ (необходимо установить ID нужного инфоблока)
$rs_Section = CIBlockSection::GetList(array('left_margin' => 'asc'), array('IBLOCK_ID' => $infoblock));
while ( $ar_Section = $rs_Section->Fetch() ) {
    $ar_Resu[] = array(  // собираем массив того, что нам нужно
        'ID' => $ar_Section['ID'], // id раздела
        'NAME' => $ar_Section['NAME'], // имя раздела (что нас, собственно, интересует)
        'IBLOCK_SECTION_ID' => $ar_Section['IBLOCK_SECTION_ID'],
    ); 
}

foreach ($ar_Resu as $section) {
   CIBlockElement::Delete($section["ID"]);
}
?>
  • Вопрос задан
  • 204 просмотра
Пригласить эксперта
Ответы на вопрос 4
можно попробовать отключить пересчет дерева или прямо из базы грохнуть
Ответ написан
@jasper-blondin
Скрипт уже закончил работу?
Я так понимаю, Вы запустили скрипт, а потом написали вопрос.

Оптимизировать можно следующим образом:
- в метод GetList добавить массив с полями выборки array("ID"), чтобы не тянуть из базы значения, которые не нужны
- выполнять метод Delete прямо в теле цикла while, чтобы не собирать без надобности массив

Если все еще не хватает времени на выполнение, написать простенькую клиентскую часть с AJAX-запросом. Будет работать медленно, но гарантировано выполнит задачу и не уйдет в таймаут.
Ответ написан
winer
@winer
занимаюсь разработкой сайтов на 1c-bitrix
При большом количестве разделов (30к+), Bitrix начинает вставлять палки в колеса как разработчику, так и пользователю, который будет работать с такими ИБ.
- Списки элементов ИБ будут безбожно тормозить в интерфейсе. На каждом хите будет добавляться фильтр по разделу.
- Редактировать их становится очень затруднительно, опять же из за долгой загрузки интерфейса и большого времени изменения.

Всё это из за того что разделы это NESTED SETS деревья. При добавлении/удалении раздела происходит вычисление LEFT_MARGIN и RIGHT_MARGIN для каждого раздела во всем инфоблоке.

Для добавления и обновления (CIBlockSection::Add, CIBlockSection::Update) есть параметр метода $bResort, который позволяет отключить этот перерасчёт в момент их выполнения.
Только после этого ОБЯЗАТЕЛЬНО надо выполнять CIBlockSection::Resort.

Это можно использовать при большом количестве операций Update и Add. Сначала выполняете все операции Update и Add с $bResort=false, а после них CIBlockSection::Resort

НО!! К сожалению, такой параметр для CIBlockSection::Delete не доступен. И вот тут начинается жесть.
Каждый вызов CIBlockSection::Delete, это:
  • пересчет границ NESTED SETS,
  • CIblockElement::GetList (поиск вложенных элементов)
  • CIblockElement::Delete (если в разделе были элементы),
  • Запрос к таблице которая хранит множественные привязки элемента к разделам (поиск значений и их удаление)
  • CIBlockSection::GetList (поиск вложенных разделов)
  • CIBlockSection::Delete (удаление вложенных разделов)
  • Переиндексирование поиска
  • Запросы к UF_* полям раздела (поиск значений и их удаление)
  • При заполненных SEO полях, запросы к таблицам которые их хранят (поиск значений и их удаление)
  • При расширенном управлении правами это еще запросы к таблицам которые хранят эти настройки (поиск значений и их удаление)


и это скорее всего не полный список, а только то что могу назвать по памяти....

Нельзя быстро удалить разделы стандартным API без написания своих запросов к БД которые проделают всё что описано выше. В идеале надо взять код стандартного CIBlockSection::Delete, внимательно его изучить и написать свой метод который будет с помощью прямых запросов делать тоже самое, но оптимально.

Если же вопрос стоит в том чтобы удалить эти разделы за ЛЮБОЕ количество времени, тогда можно написать страничку с пошаговым удалением разделов, через ajax запросы. Причем надо учитывать, что вначале разделы будут удаляться ОЧЕНЬ медленно и ajax запрос может отвалиться по таймауту, поэтому надо будет за один шаг удалять пару разделов. А ближе к границе в 10к разделов, за один шаг можно будет удалять уже большее количество.
Ответ написан
BusteR27
@BusteR27
Lead bitrix dev
Но судЯ по коду, вы собрали массив разделов и потом удаляете элементы с этими id.

Один из вариантов - выключить индексирование инфоблока модулем поиска
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
iTiPark Краснодар
от 80 000 до 120 000 руб.
Кадры-54 Новосибирск
от 65 000 до 90 000 руб.
24 марта 2019, в 11:14
5000 руб./за проект
24 марта 2019, в 09:47
8000 руб./за проект
24 марта 2019, в 05:09
60000 руб./за проект