3

I have the following apex code that runs to get the EntitySubscriptions for a set of ids so they can be deleted to clean up the chatter feed.

public static List<EntitySubscription> getAllFollowers(Set<Id> ids) {
    return [
        select parentId,
            subscriberId
        from EntitySubscription
        where parentId in :ids
        limit 1000
    ];
}

This code has been in production and running without a hitch for over a year and this past weekend, we started getting the following error everytime it runs.

System.QueryException: Non-selective query against large object type (more than 100000 rows). Consider an indexed filter or contact salesforce.com about custom indexing. Even if a field is indexed a filter might still not be selective when: 1. The filter value includes null (for instance binding with a list that contains null) 2. Data skew exists whereby the number of matching rows is very large (for instance, filtering for a particular foreign key value that occurs many times)

To make this issue even more "interesting" the error only presents itself when it is triggered by a non-system administrator. From what I was reading IN should be considered a selective query.

We currently have 89336 EntitySubscription active records and 11301 records that show up in we only look at isDeleted. This total does push us over 100000 records. Any ideas on how to make this work again?

NOTE: I did try (as a temporary solution) using Database.emptyRecyclingBin to remove the 11301 records and it would not remove them. Also trying to 'purge' them in workbench results in 'Invalid Record Id; No Recycle Bin Entry Found'

  • 1
    You're going to have to wait for the (nightly?) hard delete job salesforce runs before the query engine stops counting those deleted rows against you. – ca_peterson Apr 15 '13 at 20:27
  • Hrm, I'm not sure that's going to fix our issue then, because we've been seeing this for greater than 24hrs (if it's actually a nightly run) – Patrick Connelly Apr 15 '13 at 20:45
  • We were able to actually delete the old EntitySubscription objects and the job did come along and clean them up. So that bought us some time in prod. Also that same job made it so we could reproduce in our dev environment – Patrick Connelly Apr 16 '13 at 13:42
3

Per our chat over twitter and a related tweet from Andrew Waite I think the fix here is to remove with sharing from your class that contains the query.

While the error messaging could be improved the docs on EntitySubscription repeatedly hint that under the hood the platform has a hard time processing any reasonably large queries on this table when sharing rules have to be calculated due to the massive number of possible joins required (it's going to join to the table parentId belongs to, THEN to that record's sharing table). By running without sharing all the extra joins to enforce sharing wouldn't be needed and your query then looks much more "reasonable" to the database.

You can always use a subsequent query to UserRecordAccess to validate that the running user should be able to see all the EntitySubscriptions you fond when running without sharing if you still need to enforce security.

2

The solution (as suggested by ca_peterson on twitter) was to change the class to be without sharing to stop the sharing rules from being calculated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.