Recently, in the project that I am working on, we have received this error in our apex code and this error occurs when querying large objects using SOQL (particularly for queries inside triggers). In our case, SOQL is inside the TriggerHandler which is called by the trigger.
Developers receive this error message when a non-selective query in a trigger executes against an object that contains more than 200,000 records. To avoid this error, ensure that the query is selective.
The performance of a SOQL will depend on the presence of a selective filter(in WHERE Clause). If a SOQL query contains at least 1 selective filter, the query is said to be selective. If the SOQL query doesn’t contain a selective filter, the query is said to be un-selective and will require a full table scan.
How to determine if the query is selective?
- A query is selective when one of the query filters is on an indexed field and the query filter reduces the resulting number of rows below a system-defined threshold.
- The selectivity threshold is 10% of the first million records and less than 5% of the records after the first million records, up to a maximum of 333,333 records.
- SELECT Id FROM Account WHERE Id IN (<list of account IDs>)
Since the filter is on the ID field which is a standard and Primary Key field, it will have an index created at the DB. If SELECT COUNT() FROM Account WHERE Id IN (<list of account IDs>)returns fewer records than the selectivity threshold, the index on Id is used. This index is typically used when the list of IDs contains only a few records.
2. SELECT Id FROM Account WHERE Name != ”
Since Account is a large object even though Name is indexed (primary key), this filter returns most of the records, making the query non-selective.
3. SELECT Id FROM Account WHERE Name != ” AND CustomField__c = ‘ValueA’
Here we have to see if each filter, when considered individually, is selective. As we saw in the previous example, the first filter isn’t selective. So, let’s focus on the second one. If the count of records returned by SELECT COUNT() FROM Account WHERE CustomField__c = ‘ValueA’ is lower than the selectivity threshold, and CustomField__c is indexed, the query is selective.
For more information:
Also, there are lot of links in stack exchange which discusses this issue and you can refer them as needed: https://salesforce.stackexchange.com/search?q=Non-selective+query