@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"]);
}
?>
  • Вопрос задан
  • 7931 просмотр
Пригласить эксперта
Ответы на вопрос 4
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к разделов, за один шаг можно будет удалять уже большее количество.
Ответ написан
Комментировать
можно попробовать отключить пересчет дерева или прямо из базы грохнуть
Ответ написан
@jasper-blondin
Скрипт уже закончил работу?
Я так понимаю, Вы запустили скрипт, а потом написали вопрос.

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

Если все еще не хватает времени на выполнение, написать простенькую клиентскую часть с AJAX-запросом. Будет работать медленно, но гарантировано выполнит задачу и не уйдет в таймаут.
Ответ написан
Комментировать
BusteR27
@BusteR27
Lead bitrix dev
Но судЯ по коду, вы собрали массив разделов и потом удаляете элементы с этими id.

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

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

Войти через центр авторизации
Похожие вопросы