Another option is to call batches in chain, so you can get advantage of Database.queryLocator that is able to return more records than Iterator.
On each chain you can query the object you want to remove and delete it. You would be able to set different scopeSize for each one as well if this is required. Maybe objectA is more complex than objectB
public with sharing class MyBatch implements Database.Batchable<sObject>, Database.Stateful
{
private Integer currentChain;
private Integer scopeSize;
public MyBatch()
{
currentChain = 1;
}
public MyBatch(Integer chain)
{
currentChain = chain;
}
public Database.QueryLocator start(Database.BatchableContext BC)
{
String qry;
if(currentChain == 1)
{
qry = 'Select Id From ObjectA__c';
}
else(currentChain == 2)
{
qry = 'Select Id From ObjectB__c';
}
return Database.getQueryLocator(qry);
}
public void execute(Database.BatchableContext BC, List<sObject> scope)
{
delete scope;
}
public void finish(Database.BatchableContext BC)
{
if(currentChain == 1)
{
MyBatch mb = new MyBatch(currentChain++);
Database.execute(mb, scopeSize);
}
else(currentChain == 2)
{
sendEmail();
}
}
}