Быстрое удаление нод

Главные вкладки

Аватар пользователя aldwin aldwin 4 июня 2015 в 8:09

Доброго времени суток.
Как можно быстро удалять ноды в количестве ~1000 в час по крону. пробовал node_delete_multiple() по 150 шт., но при этом БД зависает и не отвечает секунд 30. Как можно это решить? Если удалять все sql-запросами, какие таблицы(кроме таблиц node, node_revision, field_data_field_* ) надо очищать?

Комментарии

Аватар пользователя aldwin aldwin 4 июня 2015 в 9:15

Что-то подобное получилось:

<?php
function d($nids)
{
    
$entity_type 'node';
    
$bundle NODE_TYPE_PAGE;
    
$all_field_instatnces field_info_instances($entity_type$bundle);
    foreach(
$all_field_instatnces as $field_name => $field_instance)
    {
        
$field_info field_info_field($field_name);
        if(
$field_info['type'] == 'image' || $field_info['type'] == 'file')
        {
            
// удаляем файлы, привязанные к ноде
            
            
$file_q db_select('field_data_'.$field_name'fd')->fields('fd'$field_name.'_fid');
            
$file_q->condition('fd.entity_id'$nids'IN');
            
$file_q->condition('fd.bundle'$bundle);
            
$file_q->condition('fd.entity_type'$entity_type);
            
$del_fids $file_q->execute()->fetchCol();

            

/*
            file_delete_multiple() может выполнятся долго, в зависимости от количества файлов
            в ноде. 
            */
            
file_delete_multiple($del_fids);
        }
        
$fr_q db_delete('field_revision_'.$field_name);
        
$fr_q->condition('entity_id'$nids'IN');
        
$fr_q->condition('bundle'$bundle);
        
$fr_q->condition('entity_type'$entity_type);
        
$fr_q->execute();
        
        
$nr_q db_delete('node_revision');
        
$nr_q->condition('nid'$nids'IN');
        
$nr_q->condition('bundle'$bundle);
        
$nr_q->condition('entity_type'$entity_type);
        
$nr_q->execute();
        
        
$f_q db_delete('field_data_'.$field_name);
        
$f_q->condition('entity_id'$nids'IN');
        
$f_q->condition('bundle'$bundle);
        
$f_q->condition('entity_type'$entity_type);
        
$f_q->execute();
        
        
$n_q db_delete('node');
        
$n_q->condition('nid'$nids'IN');
        
$n_q->condition('bundle'$bundle);
        
$n_q->condition('entity_type'$entity_type);
        
$n_q->execute();
    }
}
?>
Аватар пользователя aldwin aldwin 5 июня 2015 в 9:08

<a href="mailto:sas@drupal.org">sas@drupal.org</a> wrote:
node_load_multiply + node_delete - наше ВСЁ!

node_delete по одной ноде работает быстрее node_delete_multiple? Развейте мои сомнения, пожалуйста.

Сейчас у меня работает всё через node_delete_multiple и меня это не устраивает. Мне нужна скорость, и я сознательно хочу пренебречь ради этого принципами друпала и не использовать эти функции, т.к. они работают медленно в моих условиях.

Аватар пользователя gun_dose gun_dose 5 июня 2015 в 8:56

"aldwin" wrote:
1000 в час по крону. пробовал node_delete_multiple() по 150 шт., но при этом БД зависает и не отвечает секунд 30

тут только через batch можно делать, иначе ваша БД так и будет ложиться, пока хостеру это не надоест и он не заблочит ваш акк.

Аватар пользователя gun_dose gun_dose 5 июня 2015 в 10:07

"aldwin" wrote:
они работают медленно

Вы куда-то очень торопитесь или вам нужно просто, чтобы не происходил сбой при удалении?

Аватар пользователя aldwin aldwin 5 июня 2015 в 10:15

"gun_dose" wrote:
Вы куда-то очень торопитесь или вам нужно просто, чтобы не происходил сбой при удалении?

Тороплюсь. Если уменьшить количество - ноды начинают копиться.

Аватар пользователя gun_dose gun_dose 5 июня 2015 в 12:04

а через batch пробовали или нет? Там суть в том, что он может любое количество транзакций провернуть в фоне, по одной ноде за транзакцию. Понятно, что это не очень быстро, но сбой происходить не будет, никаких зависаний и таймаутов не произойдёт - всё должно будет отработать штатно.

ЗЫ: а что за прикол такой, что если удалять меньше тысячи нод в час, то они копятся? Может сперва нужно остановить генерацию нового мусора, а потом уже чистить то, что есть?

Аватар пользователя aldwin aldwin 6 июня 2015 в 11:29

"<a href="mailto:sas@drupal.org">sas@drupal.org</a>" wrote:
Попробую ещё раз раз - queue

За queue спасибо. Это оно.

"<a href="mailto:sas@drupal.org">sas@drupal.org</a>" wrote:
- node_load_multiple - есть в API
- node_delete_multiple - а это что такое ?

Есть node_load, а есть node_laod_multiple.
Есть node_delete, а есть node_delete_multiple. Вот ссылка на API.

Аватар пользователя aldwin aldwin 6 июня 2015 в 11:52

"gun_dose" wrote:
через batch пробовали или нет

Для этой задачи - не пробовал. Ну, точнее, пробовал, стандартное удаление нод сделано через batch, я его использовал и мне не понравилось. Теоретически его можно использовать, но что лучше batch или queue я пока не знаю. batch ограничивается количеством, queue - временем.

"gun_dose" wrote:
Ы: а что за прикол такой, что если удалять меньше тысячи нод в час, то они копятся? Может сперва нужно остановить генерацию нового мусора, а потом уже чистить то, что есть?

Ноды не сразу становятся мусором. Они создаются, с ними работают, по истечении какого-то срока их нужно удалить.

Аватар пользователя dashiwa dashiwa 6 июня 2015 в 13:57

Я использовал консольный скрипт когда нужно было удалить 500 000 нод за короткое время.
В вашем случае до 100 000 нод ,батч всегда отлично справится.
В вашем случае Queue API