4

On one of my sites, I have over 600 Profile 2 profile types (most of them have between 20-30 field instances, some have additional fields just used in that one type). I've tested a few different methods for bulk deletion, but can't find a way using the Entity/Profile APIs to get the deletion to occur without basically wiping out the site for a few hours.

It seems that, when a content type, profile type, etc. is deleted, a ton of caches are cleared and rebuilt for each deletion, meaning the process goes something like:

  1. Delete the entity type. (I do this part.)
  2. All the attached field instances are deleted.
  3. All the attached fields that have no other instances are deleted.
  4. All the field info and entity caches are cleared.
  5. All the caches are rebuilt (due to other visitors on the site trying to load pages which need those caches).
  6. Ready to delete another entity type.

Is there any quicker way of mass-deleting entity types (I've already removed all the entities themselves—they're quite simple and fast to remove)? I'd like to cut out steps 4 and 5, which take about 90 seconds.

(I changed to a different system for storing profiles, because the cache rebuild and memory requirements were getting out of hand with over 500 profile types (in addition to 20 other content types), and over 10,000 field instances!)

1

I decided to bite the bullet and run everything with Batch API. This meant the site was painfully slow for probably 2-3 hours, then slow for another hour or so. The profile type deletions became faster as there were fewer left to delete (since cache rebuilds were less intense the fewer field instances that were required).

I set up the batch using something like the following:

// You can remove the limit if you want, but this is a very long operation,
// so it's nice to do it in smaller chunks during traffic lulls.
$types = db_query("SELECT type FROM {profile_type} LIMIT 100")->fetchCol();
$batch = array(
  'operations' => array(
    array('mymodule_bulk_delete_profile_types', array($types))
  ),
  'finished' => 'mymodule_bulk_delete_profile_types_finished',
  'title' => t('Removing Profile Types'),
  'init_message' => t('Beginning profile type deletion...'),
  'progress_message' => t('Deleting profile types...'),
  'file' => drupal_get_path('module', 'fn_profile') . '/includes/fn_profile.utility.inc',
);
batch_set($batch);
batch_process();

Then, I had two batch callbacks (the processing function and the finished function), like so:

function mymodule_bulk_delete_profile_types($types, &$context) {
  $context['finished'] = 0;

  if (!isset($context['sandbox']['progress'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['max'] = count($types);
    $context['results']['count'] = 1;
  }

  if (!isset($context['sandbox']['types'])) {
    $context['sandbox']['types'] = $types;
  }

  $key = $context['results']['count'] - 1;
  $type_to_delete = $context['sandbox']['types'][$key];
  $profile_type = profile2_get_types($type_to_delete);
  profile2_type_delete($profile_type);

  $context['results']['count']++; // Increment the counter.
  $context['finished'] = $context['results']['count'] / $context['sandbox']['max'];

  // Show message updating user on how many profile types have been deleted.
  $context['message'] = t('Deleted @count of @total profile types.', array(
    '@count' => $context['results']['count'],
    '@total' => $context['sandbox']['max'],
  ));
}

function mymodule_bulk_delete_profile_types_finished($success, $results, $operations) {
  // Display any warnings.
  if (!empty($results['warnings'])) {
    foreach ($results['warnings'] as $warning) {
      if ($warning) {
        drupal_set_message($warning, 'warning');
      }
    }
  }
  // Set operation successful message.
  if ($success) {
    if ($results['count'] == 0) {
      $message = t("No profile types were deleted.");
    } else {
      $message = t("@count profile types deleted successfully.", array('@count' => $results['count']));
    }
  } else {
    $message = t("There were problems deleting profile types.");
  }
  drupal_set_message($message, 'status');
}

At the beginning, it was taking between 50 seconds and 80 seconds to delete a profile type. Towards the end of the batch, it was only taking about 20-30 seconds. The site now only uses about 30-40 MB (according to devel.module) when clearing all caches; it was using about 190 MB before, and taking over 2 minutes to rebuild the caches!

| 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.