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
BBeairdBBeaird 

Non-Selective query error in trigger

Stumped on an error: Non-selective query against large object type (more than 100000 rows). My query is on the assets object which does have over 700k records. However, the exact query runs fine in a class or anonymous block. It only throws the error when executing from a trigger. I've tried indexing one of the fields in the WHERE clause, but I'm still getting the error. Open ticket with Salesforce has not been helpful, so I'm rather desperate - has anyone here run into this?

 

Query:


Select id, name, SerialNumber from Asset where IsVisionLink__c = false and Exception_from_Disable__c = true  and source__c != null and source__c = 'CN_CCFL_OU'

 

 

Again - query runs just fine in an anonymous block.  The source__c field has been marked as an external id, which should mean it is indexed.  Why am I still getting this error?  Have an open ticket with Salesforce, but they have not been helpful thus far.

Best Answer chosen by Admin (Salesforce Developers) 
BBeairdBBeaird

Found a couple of other interesting things.  The query fails if I increase the LastModifiedDate range beyond 10 days:

 

Select id, name, SerialNumber from Asset where IsVisionLink__c = false and Exception_from_Disable__c = true and LastModifiedDate > :(System.now().addDays(-100)) and source__c = 'CN_CCFL_OU

 

Then I discovered the query works without error if I add a != null to the IsVisionLink__c field.  In fact, if I do that, I don't even need to use the LastModifiedDate field anymore!  This is currently working:

 

Select id, name, SerialNumber from Asset where IsVisionLink__c = false and IsVisionLink__c != null and Exception_from_Disable__c = true and source__c = 'CN_CCFL_OU'

All Answers

navneetnavneet

Hello,

 

While fatching records from trigger it has its own governer limits and its capacity of fatching records are less that apex controller. When you are runing this query from execute anonomous it consider governer limits of Apex but when you run triggers then it consider governer limits of triggers.

 

Check the size of list in apex and if it exceed governer limits then optimize your query or run the batch apex. Using batch apex you can retrive around 50 million records.

 

 

Thanks & Regards,

 

Navneet 

zachelrathzachelrath

I've run into this problem before as well. What Salesforce means by "querying on indexed fields" is this:

 

"Selective queries filter on primary keys, foreign keys, names, audit dates (such as LastModifiedDate

), or External ID fields."

 

In my case, my only WHERE condition was on a Formula Field --- which is NOT an Indexed Field, e.g.

 

[select id
from Object_With_Tons_Of_Records__c
where Formula_Field__c in :formulaFieldValues]

 

To solve it, I queried against lookup fields, which ARE indexed:

 

[select id
from Object_With_Tons_Of_Records__c
where Person__c in :contactIds
and Session__c in :sessionIds
and Formula_Field__c in :formulaFieldValues]

 

That took care of it.

 

In your case, all of the fields you're querying against are NON-indexed. I see that you're querying against several Checkbox fields, and a Picklist/Text field, all of which are NON-indexed.

 

If there are absolutely no Id or Name fields that you can query against, what you could do is to add a query condition for an audit date, i.e. query against CreatedDate or LastModifiedDate.

 

Regards,

 

Zach

 

 

BBeairdBBeaird

@navneet

That query results in a single record being returned.  I know that batch apex is an option, but I don't see why I should have to fall back on that in this situation.  While the number of records in the object is large, the number I'm actually working with is quite small.

 

@zachelrath

You are correct about the fields in my WHERE clause except for one important detail: the source__c text field IS indexed now as I have marked it as an external ID.   I also just tried using the LastModifiedDate, but the error still occurs:

 

trigger errorTest on Property__c (after update, before update) {
    List<Asset> assetsToClear = new List<Asset>();
	assetsToClear =[Select id, name, SerialNumber from Asset where IsVisionLink__c = false and Exception_from_Disable__c = true
    	and source__c !=null and source__c = 'CN_CCFL_OU'
    	and LastModifiedDate < :(System.now().addDays(-1))];
    
}

 

 

zachelrathzachelrath

Hmm --- I wonder if there is some sort of lag time on indexing?

 

Not sure if this will help, but since you're in a trigger, try refactoring your code like this:

 

trigger errorTest on Property__c (after update, before update) {
    for (List<Asset> assetsToClear : 
           [Select id, name, SerialNumber from Asset
            where IsVisionLink__c = false 
            and Exception_from_Disable__c = true
    	    and source__c !=null and source__c = 'CN_CCFL_OU'
    	    and LastModifiedDate < :(System.now().addDays(-1))] {
        for (Asset a : assetsToClear) {
            // Do something to each Asset
        }
    }
    
}

 I'm wondering if the reason the error is being thrown in the Trigger but not elsewhere is due to the SOQL query not being batched, as the for (List<SObject> lst : [SOQL]) syntax will do. Just an idea...

BBeairdBBeaird

Correction to that last post: using LastModifiedDate does work if I switch the sign to greater than.  Still, I don't understand why it's not recognizing source__c as an indexed field.

BBeairdBBeaird

Yeah, I actually tried that  exact refactoring with the thought that maybe the internal batching would do something, but the result was the same - still error.  :-(

zachelrathzachelrath

Okay, that makes more sense. If LastModifiedDate didn't count as indexed, I'd definitely be worried. But as far as your ExternalId field, I'd bet that there's lag time on the indexing. Since you have some 700,000 Asset records, I'd bet that Salesforce is still indexing the Source__c field. I'd be interested to see if you tried this again later today, without the LastModifiedDate criterion, to see if it worked. That would probably confirm the indexing-lag-time theory.

BBeairdBBeaird

A lag time would make sense, however, I set the index yesterday afternoon and after about 30 minutes got an e-mail from salesforce saying the process was completed.  Seems like it definitely would have finished by now.  And when I look at source__c in my Asset object, it does indeed say "External ID" next to the field.  I have double-checked to make sure all this is happening in the same sandbox.  Here's the e-mail text they sent:

 



Force.com Sandbox

Your request to build an index by using either an external ID or a uniqueness attribute on the following field has successfully completed: SOURCE.

BBeairdBBeaird

Found a couple of other interesting things.  The query fails if I increase the LastModifiedDate range beyond 10 days:

 

Select id, name, SerialNumber from Asset where IsVisionLink__c = false and Exception_from_Disable__c = true and LastModifiedDate > :(System.now().addDays(-100)) and source__c = 'CN_CCFL_OU

 

Then I discovered the query works without error if I add a != null to the IsVisionLink__c field.  In fact, if I do that, I don't even need to use the LastModifiedDate field anymore!  This is currently working:

 

Select id, name, SerialNumber from Asset where IsVisionLink__c = false and IsVisionLink__c != null and Exception_from_Disable__c = true and source__c = 'CN_CCFL_OU'

This was selected as the best answer
zachelrathzachelrath

Wait, this may be the problem --- did you have Salesforce.com Index the Source__c field in your Sandbox, or in your Production org? If you only did it in your Sandbox org, then there's no reason to expect it was done in your Production org as well. 

BBeairdBBeaird

Yes, the index is only in the sandbox, but I've been working in sandbox the entire time.  None of my troubleshooting has been in production.

CholericCholeric

Hi,

 

just in case this Problem is still unsolved...

Try to resort your where clause - order important parts (indexed fields) first before.

 

"Select id, name, SerialNumber from Asset where source__c = 'CN_CCFL_OU' and IsVisionLink__c = false and Exception_from_Disable__c = true"

 

This should speed up the query - not quite sure if it helps on the non-selective issue too.

 

regards,

Stefan