+ Start a Discussion
AshlekhAshlekh 

Heap Size Issue

Hi,

I've an issue with Heap Size.

Basically I've a project there is a functionality in which many records are updating and many new records are creating on single event.

In my org I am near to hit SOQL limit so that I fetch all the records of A object in one time and it is almost 15K records which are maintaining in the list and it consume 4Mb of heap. 

If I write some other functions and will try to fetch some more data from other object than my code will cross the heap size limit.

Some one told me that why you are fetching the data of A object (!5K). instead of this you can query on Object A when you need data for this. 
but in that case I was facing SOQL limit and that data is required for some other code in the context because 
I need to update some other records bases on value in A object records.

Can some will provide a better approach to reduce the heap size?

All my code is running in the trigger.

-Advance Thanks
Ashlekh Gera
Amit Chaudhary 8Amit Chaudhary 8
Please check below post. I hope that will help u
1) https://help.salesforce.com/apex/HTViewSolution?id=000170956&language=en_US (https://help.salesforce.com/apex/HTViewSolution?id=000170956&language=en_US)
2) https://help.salesforce.com/HTViewSolution?id=000004186&language=en_US (https://help.salesforce.com/HTViewSolution?id=000004186&language=en_US)
3) http://blog.jeffdouglas.com/2010/08/16/managing-the-heap-in-salesforce-com/
4) https://www.sundoginteractive.com/blog/system.limitexception-apex-heap-size-too-large

In the below sample, while we could be processing 50000 items, the largest heap would contain a search term, a query, a list of 200 accounts, and a list of the results. This is relatively small in the scope of everything that's being processed
public with sharing class myClass{

private String myString;

    public myClass(String searchString) {
        myString = searchString;
    }

    private string getQueryString() {
        return 'SELECT Id, Name FROM Account LIMIT 50000';
    }

    public List<Account> getSearchResults() {
        List<Account> searchResults = new List<Account>();
        for(List<Account> accts : Database.Query(getQueryString())) {
            // Each loop processes 200 items
            for(Account a : accts) {
                if (a.Name != null && a.Name.contains(myString)) {
                    searchResults.add(a);
                }
            }
        }
        return searchResults;
    }
}
Please let us know if this will help you

Thanks
Amit Chaudhary
 
srlawr uksrlawr uk
This sounds like a pretty heavyweight opperation you are doing! Without seeing the code (and I kind of don't want to!) its hard to advise on the best courses of action, but here are a few thoughts:

1) Why are you so high on SOQL queries. I have battled a few orgs where a transaction is up in the 90's and just by thinking about data re-use and this little trick here about not needing to query for inserts (http://srlawr.blogspot.co.uk/2013/07/reducing-soql-queries-in-triggers-by.html).. You can sometimes save 20 - 30% of them.. thus allowing you to break your work into more manageable chunks (If you can "reuse" a list or map of 5k records 3 times instead of having a 15k record list, you will be laughing)

2) Why do you need all 15k records in memory? Is there really no way to filter them down, or put some sort of selector on the SOQL query?

3) You you write a public inner class that housed JUST the data you wanted from these 15k records and then load them all into that and NULL out the original list? Something like:
 
public List<myObj> getAccounts() {
    List<myObj> results = new List<myObj>(); 
    for(Account thisAcc: [SELECT Id, Name FROM Account]) {
       thisAcc.add(new myObj(thisAcc.name);   
    }
    return results;
}


public class myObj {
   public string name { get; set; }
    public myObj(String name){
        this.name = name;
    }
}
that way the massive list of your objects is never fully in memory, and the inner classes should hopefully be WAY smaller than a list of sObjects?

4) Could you somehow instead set a flag on the affected records and then a future method to do your processing? You get 12Mb of heap then... https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm


I hope that helps?

 
AshlekhAshlekh

Hi srlawr uk,

Thanks for reply over this.

1) Actually in my porject (it is a big project) there are a lot of fuctionality is connected to other functionality or flow. Some time we get a notification from third party and then we need to update many records at least 10-12 objects records need to update basis on some criteria, in my project there are some new folks which are not following best practise and some time code need query in for loop (you will be laughing now).I just joined this project and need to fix all this mashup. So we are near to SOSL limit.

2) We need 15K record be becuase we are near to SOSL limit we don't want to query again-again on Object A, we are query on this object in the initial point of trigger or starting point because we don't know when we need record of A object so we can collect the id of A object record and then query only those records, so instead of collecting of Id's we are retriving all the records and it is increasing the Heap Size- I am working on thsi and trying to put some where clause or filtering the record but realy very hard to recoginze the right id records.

3) As you suggest we need to create wrapper and contain only those record which are requried. Number of records in the code is very large ( working on this ) but yes we are only included those fields which are required.

4)  This is our last approch as we need to shift all major part of code in Future method.

I Just want to know there is any other way where we can keep  15K data without increasing heap (I know it is laughing question ) but may be some have answer for this.


@Amit Chaudhary 8 - Thanks for your suggestion, I will go through the links and will let you know if I need any info.

-Thanks
Ashlekh Gera