1

I am building a SOQL FOR LOOP and I am wondering whether or not I am getting the advantages by abstracting the SOQL Query to a separate Selector class. Should I instead be placing the SOQL Query directly within the FOR LOOP? I am trying to avoid Apex Heap Size Limit Exceptions.

FOR LOOP

        for (
            OpportunityContactRole ocr : ocrSelector.getOpportunityContactRolesByContactIdsAndOpportunityIds(
                contactIdToTargetOpportunityId.keySet(),
                contactIdToTargetOpportunityId.values()
            )
        ) {
            contactIdToTargetOpportunityId.remove(ocr.ContactId);
        }

SELECTOR CLASS

public List<OpportunityContactRole> getOpportunityContactRolesByContactIdsAndOpportunityIds(
    Set<Id> contactIds,
    List<Id> opportunityIds
) {
    return [
        SELECT Id, ContactId, OpportunityId
        FROM OpportunityContactRole
        WHERE ContactId IN :contactIds AND OpportunityId IN :opportunityIds
        WITH SECURITY_ENFORCED
    ];
}
2
  • Fundamentally you do lose the heap control benefit, but this may mot be relevant depending the number of records you will have returned.
    – Phil W
    Feb 2, 2023 at 20:44
  • 1
    Notwithstanding the answers here and depending on the application, Selector classes have huge advantages in terms of reuse and even more, they can be mocked with dependency injection so you can avoid in many unit tests inserting test data w/ DML. See this Trailhead and for mocking, this video series
    – cropredy
    Feb 2, 2023 at 21:35

2 Answers 2

0

You don't need to be worried about heap size, unless you are querying a very large amount of records or records with fields that contain a very large amount of data.

Heap size is either 6 or 12 MB (the latter if the code is run asynchronously), your average query results will be a tiny fraction of that.

Considering the above, more maintainable code is likely a more important factor than this limit.

1
  • You can test this out in the developer console logs, check the difference in the heap size usage between both methods of querying data. It may not register at all. Feb 2, 2023 at 19:34
0

Abstracting the SOQL query to a separate Selector class can be beneficial for code organization and maintainability, as well as for reuse of the query logic.

However, in terms of avoiding heap overflow (Apex Heap Size Limit Exceptions), it is recommended to use the FOR LOOP and query only the necessary data in smaller batches, rather than querying all the data in one go.

You can use the LIMIT clause in your SOQL query to limit the number of records being queried at a time, and use the OFFSET clause to retrieve the next batch of records in the next iteration of the loop.

5
  • So are you saying that the system will perform the exact same way regardless of whether or not I abstract the SOQL query? I don't think this query can every return more than 200 records in a trigger context. In a perfect case, it will have 200 contact ids, and 200 differing opportunity ids. It will only return the opportunity contact roles matching contacts which exist already. So I am not sure this is even where I am running into apex heap limit exceptions.
    – Coova
    Feb 2, 2023 at 19:20
  • No, abstracting the SOQL query to a separate class does not affect the performance of the query. Whether the query is placed directly within the FOR LOOP or in a separate Selector class, it will perform the same way.
    – VikMants
    Feb 2, 2023 at 19:25
  • If your query is not returning more than 200 records, it is unlikely that you will run into Apex Heap Size Limit Exceptions in this scenario. However, it is still a best practice to limit the amount of data being queried and processed at once, especially in a trigger context where multiple operations are being performed. This can help prevent performance issues and optimize the overall efficiency of your code.
    – VikMants
    Feb 2, 2023 at 19:25
  • @Coova on its own, the average query will need a lot more than 200 records to come close this exception Feb 2, 2023 at 19:32
  • @MenachemShanowitz you are correct. Heap Limit is typically encountered when a large amount of data is being processed, such as when a query returns a large number of records. In such cases, it is common to see this exception even when the query itself returns fewer than 200 records. This is because the heap size limit is determined by the total amount of memory used by your Apex code, not just by a single query. To avoid this exception, it's important to limit the amount of data being processed at once, and to structure your code in a way that optimizes performance and reduces memory usage.
    – VikMants
    Feb 2, 2023 at 19:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .