function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ScorpioScorpio 

How to process more than 50,000 records for a single record returned from start method in batch Apex

Hi,

 

I have a situation here. I have a custom object lets say SAAS_Profile__c. It has 2 text fields that contain queries like :

 

Query_Total_Records__c  : Select Count() FROM Case where RecordTypeID='012a0000001RRKBAA4' 

 

Query_Records_Per_Week__c : Select Count() FROM Case where RecordTypeID='012a0000001RRKBAA4'  and CreatedDate = LAST_N_DAYS:7

 

Now my requirement is I have to get all the rows of   SAAS_Profile__c object(total rows less than 100). And for each row returned I have to execute these 2 queries and update 2 fields : Records_pWeek__c(for weekly counts) and Records_Total__c (Total record count). These 2 fields are for statistics purposes and we intend to run this batch job on a weekly basis. Each row of this SAAS_Profile__c object queries on different objects both custom and standard . Here is the batch job that I have written:

 

global class batchSAASProfileUpdate implements Database.Batchable<sObject>
{
global Database.QueryLocator start(Database.BatchableContext BC)
{
String query = 'SELECT Id,Name,Query_Records_Per_Week__c,Query_Total_Records__c,Records_pWeek__c,Records_Total__c FROM SAAS_Profile__c where Query_Records_Per_Week__c !=\'\' and Query_Total_Records__c != \'\') ';
system.debug('Query String : '+query);
return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List<SAAS_Profile__c> scope)
{
system.debug('******************Inside execute');
for(SAAS_Profile__c s : scope){
String queryPerWeek = s.Query_Records_Per_Week__c;
String queryTotalRec = s.Query_Total_Records__c;
system.debug('****************name :'+ s.name +'values : queryPerWeek :'+queryPerWeek +' queryTotalRec '+queryTotalRec );
try{
s.Records_pWeek__c = Database.countQuery(queryPerWeek);
s.Records_Total__c = Database.countQuery(queryTotalRec);
system.debug('****************values : s.Records_pWeek__c :'+s.Records_pWeek__c+' s.Records_Total__c '+s.Records_Total__c );
update s;
}
catch(Exception e){
system.debug('********Exception occured' + e.getMessage());
}
}

}
global void finish(Database.BatchableContext BC)
{
}
}

 

This batch job is working for the records that have total count values < 50,000. Its failing for the count() more than that. I am stuck here. I dont know how to work around this issue. Any help is really appreciated. This is really critical for us now!

 

 

Best Answer chosen by Admin (Salesforce Developers) 
souvik9086souvik9086

Use the Database.QueryLocator object when you are using a simple query (SELECT) to generate the scope of objects used in the batch job. If you use a querylocator object, the governor limit for the total number of records retrieved by SOQL queries is bypassed. For example, a batch Apex job for the Account object can return a QueryLocator for all account records (up to 50 million records) in an organization. 

For reference http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_batch_interface.htm

 

It will execute upto 50 million records as it will execute 200 records chunk once. So it is nothing with >50k or <50k.

May be something else which is causing the error.

 

Also you are updating inside for loop. Add them in a list and update that list outside for loop.

All Answers

souvik9086souvik9086

Use the Database.QueryLocator object when you are using a simple query (SELECT) to generate the scope of objects used in the batch job. If you use a querylocator object, the governor limit for the total number of records retrieved by SOQL queries is bypassed. For example, a batch Apex job for the Account object can return a QueryLocator for all account records (up to 50 million records) in an organization. 

For reference http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_batch_interface.htm

 

It will execute upto 50 million records as it will execute 200 records chunk once. So it is nothing with >50k or <50k.

May be something else which is causing the error.

 

Also you are updating inside for loop. Add them in a list and update that list outside for loop.

This was selected as the best answer
GunishGunish
Hi Scorpio,

Have you had a look at @Readonly annotation.
If you are not performing any DML Operations. Then you can definitely use this to solve your problem!


Sometimes, it is also advisable to break down your page into two parts, 1 part to retrieve the data, by using the readonly annotation, and the other part to perform the DML operation separately.

Here is a link.
http://www.salesforce.com/us/developer/docs/pages/index_Left.htm#StartTopic=Content/pages_controller_readonly_context.htm


-Gunish
ScorpioScorpio

Thanks for the response Souvik can I use Qury locator inside the ececute method too? If yes then my problem is solved. Yeah I notice that update in for loop will change it definitely.

ScorpioScorpio

Hi Gunish, Will the @readonly let us update too?

ScorpioScorpio

Thanks For pointing me to the correct API my issue is solved.