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
Subodh Shukla 16Subodh Shukla 16 

How to resolve the error:: execution of AfterUpdate caused by: System.QueryException: Non-selective query against large object type (more than 200000 rows)

public class InvoiceTriggerHelper {
        public static void updateInvoice(List<cma_Invoice__c> lstInvoice){
            System.debug('lstInvoice'+lstInvoice);
            
            Map<Id, List<cma_Invoice__c>> acctIdinvoiceListMap = new Map<Id, List<cma_Invoice__c>>();
            Set<Id> acctIds = new Set<Id>();
            List<cma_Invoice__c> invoiceList = new List<cma_Invoice__c>();
            for(cma_Invoice__c invoice : lstInvoice){
                system.debug('invoice.cma_Account__r.id--->'+invoice.cma_Account__c);
                if(invoice.cma_Account__c != null){
                    acctIds.add(invoice.cma_Account__c);
                }
            }
            system.debug('acctids--->'+acctIds);
            if(acctIds.size() > 0){
        invoiceList = [SELECT sic_Invoice_Amount_EUR_current_year__c, sic_Invoice_Volume_Tons_current_year__c, cma_Account__c FROM cma_Invoice__c WHERE cma_Account__c IN : acctIds];
        
        for(cma_Invoice__c invoice : invoiceList){
            if(!acctIdinvoiceListMap.containsKey(invoice.cma_Account__c)){
                acctIdinvoiceListMap.put(invoice.cma_Account__c, new List<cma_Invoice__c>());
            }
            acctIdinvoiceListMap.get(invoice.cma_Account__c).add(invoice);
        }

        List<Account> acctList = new List<Account>();
        acctList = [SELECT sic_Actuals_YTD_turnover_EUR__c, sic_Actuals_YTD_Volume_Tons__c FROM Account WHERE Id IN: acctIds];
        for(Account acct : acctList){
            List<cma_Invoice__c> tempinvoiceList = new List<cma_Invoice__c>();
            tempinvoiceList = acctIdinvoiceListMap.get(acct.Id);
            Double totalturnover = 0;
            Double totalVolume = 0;
            if(tempinvoiceList!=null && !tempinvoiceList.isEmpty()){
                for(cma_Invoice__c invoice : tempinvoiceList){
                    if(invoice.sic_Invoice_Amount_EUR_current_year__c != null){
                      totalturnover += invoice.sic_Invoice_Amount_EUR_current_year__c;
                    }
                    if(invoice.sic_Invoice_Volume_Tons_current_year__c !=null){
                        totalVolume += invoice.sic_Invoice_Volume_Tons_current_year__c;
                    }
                }
            }
            acct.sic_Actuals_YTD_turnover_EUR__c = totalturnover;
            acct.sic_Actuals_YTD_Volume_Tons__c = totalVolume;
        }
        update acctList;
            }
        }
    
   
    }
Where Account is having lookup relationship so it is already indexed  please let me know how we can over come this error

Thanks: 
Subodh Shukla
 
Raj VakatiRaj Vakati
You need to use the Index fields in where condition in SOQL if you have more than 200000  records 

If you're running a trigger on objects that have more than 200,000 records, it's possible that you'll receive the error, "System.QueryException: Non-selective query against large object type." We'll go over the a few possible fixes. 


1. You may find that the query in question needs to be more selective in the WHERE clause. According to the Salesforce standards & best practices - the where clause needs to subset 10% or less of the data.
2. A custom index on the field.
3. A possible quick fix may be to make the field in question an external ID. Since external IDs are indexed automatically, this will create the index and may solve the problem.

In Classic, go to Setup -> Create -> Objects then click the Object name. 
In LEX, go to Setup -> Object Manager  then Object name.
Then, edit field name and check the box External ID.

NOTE: If this does help your query performance, we recommend that you still log a case with support to implement a custom index in it's place. This is not a long term solution for performance improvements and has other designed use cases.
Read our Make SOQL query selective help article for more information on indexing.

https://help.salesforce.com/articleView?id=000002493&type=1

 
public class InvoiceTriggerHelper {
        public static void updateInvoice(List<cma_Invoice__c> lstInvoice){
            System.debug('lstInvoice'+lstInvoice);
            
            Map<Id, List<cma_Invoice__c>> acctIdinvoiceListMap = new Map<Id, List<cma_Invoice__c>>();
            Set<Id> acctIds = new Set<Id>();
            List<cma_Invoice__c> invoiceList = new List<cma_Invoice__c>();
            for(cma_Invoice__c invoice : lstInvoice){
                system.debug('invoice.cma_Account__r.id--->'+invoice.cma_Account__c);
                if(invoice.cma_Account__c != null){
                    acctIds.add(invoice.cma_Account__c);
                }
            }
            system.debug('acctids--->'+acctIds);
            if(acctIds.size() > 0){
        invoiceList = [SELECT sic_Invoice_Amount_EUR_current_year__c, sic_Invoice_Volume_Tons_current_year__c, cma_Account__c FROM cma_Invoice__c WHERE cma_Account__c IN : acctIds AND cma_Account__c!=NULL ];
        
        for(cma_Invoice__c invoice : invoiceList){
            if(!acctIdinvoiceListMap.containsKey(invoice.cma_Account__c)){
                acctIdinvoiceListMap.put(invoice.cma_Account__c, new List<cma_Invoice__c>());
            }
            acctIdinvoiceListMap.get(invoice.cma_Account__c).add(invoice);
        }

        List<Account> acctList = new List<Account>();
        acctList = [SELECT sic_Actuals_YTD_turnover_EUR__c, sic_Actuals_YTD_Volume_Tons__c FROM Account WHERE Id IN: acctIds];
        for(Account acct : acctList){
            List<cma_Invoice__c> tempinvoiceList = new List<cma_Invoice__c>();
            tempinvoiceList = acctIdinvoiceListMap.get(acct.Id);
            Double totalturnover = 0;
            Double totalVolume = 0;
            if(tempinvoiceList!=null && !tempinvoiceList.isEmpty()){
                for(cma_Invoice__c invoice : tempinvoiceList){
                    if(invoice.sic_Invoice_Amount_EUR_current_year__c != null){
                      totalturnover += invoice.sic_Invoice_Amount_EUR_current_year__c;
                    }
                    if(invoice.sic_Invoice_Volume_Tons_current_year__c !=null){
                        totalVolume += invoice.sic_Invoice_Volume_Tons_current_year__c;
                    }
                }
            }
            acct.sic_Actuals_YTD_turnover_EUR__c = totalturnover;
            acct.sic_Actuals_YTD_Volume_Tons__c = totalVolume;
        }
        update acctList;
            }
        }
    
   
    }

 
Abdul KhatriAbdul Khatri
Hi Subodh,

You must always find solution optimizing your code for a very selective SOQL instead of relying of field index which may endup failing if you don't control your data that has a tendency to grow in future.

With the amount of data your are referring I would suggestion few following approaches
  1. Put if checks consider records only where Amount relevant fields changes happened.
  2. If you are really expecting 200000 then I don't think that amount of people making inserts/updates at the same time, it may be some process doing that so I would suggest to move that to Batch Apex.
  3. Move your method to Future or use Queueable Apex
Anyway I tried to shorten your code and here it is. It is 10 lines then yours with the removal of twoSOQL and a FOR...LOOP. Use it if you need it
public class InvoiceTriggerHelper {
    public static void updateInvoice(List<cma_Invoice__c> lstInvoice){
        System.debug('lstInvoice'+lstInvoice);
        
        Map<Id, List<cma_Invoice__c>> acctIdinvoiceListMap = new Map<Id, List<cma_Invoice__c>>();
        List<cma_Invoice__c> invoiceList = new List<cma_Invoice__c>();       
        for(cma_Invoice__c invoice : lstInvoice){
            system.debug('invoice.cma_Account__r.id--->'+invoice.cma_Account__c);
            if(invoice.cma_Account__c != null){
            	if(!acctIdinvoiceListMap.containsKey(invoice.cma_Account__c)){
                	acctIdinvoiceListMap.put(invoice.cma_Account__c, new List<cma_Invoice__c>());
            	}
            	acctIdinvoiceListMap.get(invoice.cma_Account__c).add(invoice);
            }
        }            
        if(acctIdinvoiceListMap.isEmpty()) return;       	
        for(Id acctId : acctIdinvoiceListMap.KeySet()){
            Double totalturnover = 0;
            Double totalVolume = 0;
            if(acctIdinvoiceListMap.get(acctId) != null && !acctIdinvoiceListMap.get(acctId).isEmpty()) continue;
            List<Account> acctList = new List<Account>();
            for(cma_Invoice__c invoice : acctIdinvoiceListMap.get(acctId))
            {
                if(invoice.sic_Invoice_Amount_EUR_current_year__c != null){
                    totalturnover += invoice.sic_Invoice_Amount_EUR_current_year__c;
                }
                
                if(invoice.sic_Invoice_Volume_Tons_current_year__c !=null){
                    totalVolume += invoice.sic_Invoice_Volume_Tons_current_year__c;
                }
            }
            Account acct = new Account (Id = acctId);
            acct.sic_Actuals_YTD_turnover_EUR__c = totalturnover;
            acct.sic_Actuals_YTD_Volume_Tons__c = totalVolume;
            acctList.add(acct);
        }
        update acctList;
    }
}

Let me know your thoguts.