11

I have about 13000 nodes to delete in a Drupal 7 site. I have tried the Views Bulk Operations module to delete 500 nodes at a time, but it times out. I can only delete 50 nodes at time.

How can I delete more than 50 nodes at time?

  • There used to be "bulk delete" module, but got obsolete in favor of VBO anwyay. But VBO seems to support batch processing. Have you tried to use it? – Mołot Jun 14 '13 at 9:36
  • 1
    VBO, as indicated in the answers below, is probably the way to go. What I've done at times of needing to delete a magnitude more nodes than in this case, is hack module invoke to ignore lots of hooks invocations that I don't need. (My worst offender was apache solr). This can significantly speed up the work, but obviously must be done with great care. – Letharion Jun 14 '13 at 9:54

10 Answers 10

18

VBO is the de facto standard for bulk-deleting nodes, there simply isn't a better way to do it.

As VBO processes in batches it only does 1 (or maybe a couple) of nodes at a time. So if you're receiving timeout errors those are related to the deletion of a single node, not to the entire batch operation.

The standard resolution to something like this is to increase the PHP max execution time to compensate.

| improve this answer | |
  • 3
    Just to complete the answer: You can choose how many entities should be picked up for the operation. Using 100 will do fine in ~1 minute from my experience. – AyeshK Jun 14 '13 at 19:29
8

Install Devel. Then go to admin/config/development/generate/content in D7 and select all content type. Check "Delete All content". Enter 0 in "How many nodes would you like to generate? "

Click Generate.

That'll delete all nodes.

| improve this answer | |
  • 1
    @Mołot 'Check "Delete All content"'... 'Enter 0 in "How many nodes would you like to generate? "' ...;) – Clive Jun 14 '13 at 9:40
  • @Clive OK, my mistake, sorry. – Mołot Jun 14 '13 at 9:42
  • 1
    Specifically, it's the Devel Generate module that does this; it ships with Devel, but you won't get this functionality if you just enable Devel. You can also easily delete all nodes of a certain content type this way, if you don't want to delete everything. If you're still getting PHP timeouts and aren't afraid of the CLI, you can also use the Drush generate-content (genc) command that comes with Devel Generate; drush help genc for usage info. – Garrett Albright Jun 14 '13 at 15:00
4

Use a VBO and execute it from Drush. I used the following method to delete over 1.5million nodes after scale testing.

  1. Create a new view with a page. Set the filters appropriately to display only the type of nodes you'd like to delete.
  2. Add a new field: "Bulk operations: Content"
  3. Check the box next to "Delete item" under 'Selected bulk operations'.
  4. Save the view.
  5. Assuming you know how to use Drush, run this command: (Use a linux 'screen' to run uninterrupted for big datasets)

drush vbo-execute my_view action::views_bulk_operations_delete_item

Where, my_view is the machine name of your view

You can also use drush vbo-list to display all available views and their bulk operations.

The VBO should now run in the shell, giving you feedback as it goes.

| improve this answer | |
3

There is a Delete All module out there. It will delete all the nodes and/or users from the site.

It also has Drush support:

Examples:

drush delete-all article             Delect all article nodes.  
drush delete-all all                 Delete nodes of all types.  
drush delete-all --reset             Delete nodes of all types, and reset node, revision and comment counters.  
drush delete-all users               Delete users.
| improve this answer | |
  • 7
    I'd strongly recommend not using this module - it sets a time limit of 30 seconds on the script, and runs through each and every node individually, calling node_delete() (it doesn't even bother to use node_delete_multiple()). Even more worryingly, it has an option that deletes data directly from the database tables without using the field API, and without using hooks. No batch jobs at all, it just runs until the script dies. Very dangerous module IMHO. – Clive Jun 14 '13 at 9:45
  • 2
    Could still be useful if you know what you're doing, and take backups. Deleting thousands of nodes while invoking all hooks and apis can be painfully slow. :( – Letharion Jun 14 '13 at 9:51
  • @Letharion No pain, no gain ;) You're right of course, I though I'd just better slap a disclaimer on this as this module could make things messy if in the wrong hands! – Clive Jun 14 '13 at 9:53
  • @Clive With drush support if I get to do drush delete-all article to delete articles I'd go for this solution. – AjitS Jun 14 '13 at 10:24
  • @develkar For a few hundred nodes that might be fine, but the drush extension uses exactly the same functions as the on-site version so it's still just as susceptible to timeouts unfortunately – Clive Jun 14 '13 at 10:30
1

Use Views Bulk Operations - it was a good idea. But instead of calling operation directly, use batch api. Here you can read shor article about it. Lack of documentation on that part was a known problem.

| improve this answer | |
1

For deleting nodes in large number(i.e is bulk) like in your case, you could also use Bulk delete module for this.

That will use the Batch API to delete the nodes to avoid timeout or memory issues when deleting thousands of nodes with a single call to node_delete_multiple().

Apart from this,you can even try Delete all module for deleting all the nodes of a content type.

Hope this helps.

| improve this answer | |
1

You can also create batch process for it using BATCH API and in that batch process just do

foreach($nodes as $node){ node_delete($node[nid]);}

Thats it. You are done here. If you wish to create a drush command for it, you can also create it. For reference please look at this.

| improve this answer | |
1

If you have reason to do it by code:

$query = new EntityFieldQuery();

$query->entityCondition('entity_type', 'node')
  ->propertyOrderBy('nid', 'DESC')
  ->range(1000, 1000);

$result = $query->execute();
node_delete_multiple(array_keys($result['node']));

You also have many other available methods to select nodes to delete.

| improve this answer | |
1

You can take Bobik's advise and feed that as the argument of a 'drush php-eval' if you're really in a pinch, but I would expect that the performance will be similar to that of VBO, while being slightly faster. If performance is really slow, you might wish to take a look at what modules are calling hook_node_delete by grepping the codebase for '_node_delete(' and then determining whether or not you can disable some of the modules which are using that hook.

| improve this answer | |
1

On Drupal 8, an other way is to delete multiple entities without loading them all at a time but by chunk.

You can use less memory and have great performance :

$nids = \Drupal::entityQuery("node")
  ->condition("type", "my_bundle")
  ->execute();

$storage_handler = \Drupal::entityTypeManager()->getStorage("node");

if (!empty($nids)) {
  foreach (array_chunk($nids, 50) as $chunk) {
    $nodes = $storage_handler->loadMultiple($chunk);
    $storage_handler->delete($nodes);
  }
};

For more convenience, you can trigger it inside drush command php-eval :

drush php-eval '$nids = \Drupal::entityQuery("node")->condition("type", "my_bundle")->execute(); $storage_handler = \Drupal::entityTypeManager()->getStorage("node"); if (!empty($nids)) {   foreach (array_chunk($nids, 50) as $chunk) { $nodes = $storage_handler->loadMultiple($chunk); $storage_handler->delete($nodes); }};'
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.